0

I find strings or character arrays in C confusing, so I tend to make mistakes and errors while writing code. The below code takes in a character array and while printing, prints the fourth element as x.

void printString(char stuff[]) {
    for (int i = 0; i < 5; i++) {
        if (i == 3) {
            stuff[i] = 'x';
        }
        printf("%c", stuff[i]);
    }
}

int main(void) {
    char z[] = "hello";
    printString(z); // output helxo

When trying to apply the same concept with an array of character arrays, you can't change the values

void printStrings(char stuff[5][20]) {
    for (int i = 0; i < 5; i++) {
        if (i == 4) {
            stuff[i] = "Not Cool"; // Error: assignment to expression with array type
        }
        printf("%s\n", stuff[i]);
    }
}

int main(void) {
    char a[5][20] = {
        "Words",
        "More Words",
        "Letters",
        "Arrays",
        "Cool"
    }
}

Any help would be appreciated.

P.S. Any links to a resource explaining character arrays and strings would also be helpful :)

0

4 Answers 4

2

The = operator is not defined to copy the contents of one array to another. You either have to copy each array element individually in a loop:

for ( size_t i = 0; i < num_elements; i++ )
  dst[i] = src[i];

or you have to call a library function like strcpy (for arrays that contain strings) or memcpy (for arrays that don't contain strings), which does pretty much the same thing under the hood.

Arrays and array expressions in C are weird compared to other aggregate types like struct or union; as part of that weirdness, array expressions are not allowed to be the target of an assignment operator. Under most circumstances, an expression of type "array of T" is converted, or "decays", to an expression of type "pointer to T" and the value of the expression is the address of the first element of the array.

This isn't arbitrary - Ritchie had a reason for making arrays behave this way - but it doesn't make it any less weird.

Sign up to request clarification or add additional context in comments.

Comments

1

When trying to apply the same concept with an array of character arrays, you can't change the values

Yes you can, just not the way you are doing it. You can't assign one array to another. But you can use strcpy() instead to copy characters from one array to another, eg:

strcpy(stuff[i], "Not Cool");

Or better, strncpy(), eg:

strncpy(stuff[i], "Not Cool", 20);

5 Comments

What's the point of using strncpy here? Either the buffer is long enough, then strcpy is OK, or the buffer is not long enough, and in that case the string will be copied partially leaving the copied string without a NUL terminator which is hardly better than a buffer overflow.
@Jabberwocky you can always force a null terminator if needed: strncpy(stuff[i], "Not Cool", 20); stuff[i][19] = '\0'; Or, you can simply tell printf() to not rely on a null terminator: printf("%.20s\n", stuff[i]);
@RemyLebeau, forcing a zero termination on a partially copied string may cause a new class of bugs if you depend on the string being copied completely. Those bugs may even be harder to catch than missing zero termination, or buffer overflow.
@HAL9000 well, if you depend on strings that are larger than the buffer, you have other problems anyway.
@RemyLebeau, My point is that "fixing" a partially copied string by adding a zero termination, is just hiding the problem. It doesn't fix anything. Better to call abort if the program can't handle it correctly. But this is getting OT, so I'm signing off
1

When trying to apply the same concept with an array of character arrays, you can't change the values

The problem is not that you cannot change the values. It is exactly as the compiler tells you: you cannot assign to whole arrays.

Given this declaration:

void printStrings(char stuff[5][20]) {

Parameter stuff is a pointer to an array of 20 chars. stuff[4] therefore designates an array, and is not an lvalue -- you cannot assign to it. But you can modify its elements via assignment, or, more generally, you can modify its contents via appropriate functions, such as strcpy().

    stuff[4][0] = 'f';

I find strings or character arrays in C confusing

There are some confusing things about C strings, but one thing that I hope will help you is to recognize that strings and character arrays are not the same thing. Strings are values that may be represented by the contents of character arrays. Even when a character array contains a string (because any one or more of its elements has value '\0' and therefore serves as a string terminator) the array itself is not the string, even though we are sometimes a bit lax with our language around such things.

Compound that with the fact that string literals have their own quirks, and arrays in general have quirks, and yes, there is plenty of room for confusion.

Comments

0

The misconcept you have comes from the fact that you think that arrays are assignable, as are other objects. The C concept of array is a bit poor. When you use the array identifier as a whole, you are not meaning the whole array, but just the (constant) address of it's first element (like with a pointer), so you cannot write something like:

char A[100], B[100];
A = B; /* error, A is a constant address (the address of A array) and B is a constant address, so A is not assignable. */

This is very efficient when passing arrays as parameters to functions, because it avoids to copy the whole array into the parameter list, and just a pointer is put in it. It also freed the original C implementors to write code to copy full blocks of memory when you assigned arrays (which is something that is scarcely used in programming)

To provide a solution, they wrote a family of functions that allow you to copy arrays or strings (which are arrays of char). You can use:

#include <string.h>
...
       strcpy(stuff[i], "Not cool");

and this will make the string literal to be copied at position of the i-esim array element.

You stated that

When trying to apply the same concept with an array of character arrays, you can't change the values

but in your first case you were assigning a single char object (which as an scalar value is assignable in C) when you switched to arrays, you got to the fact that a whole array is not assignable in C.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.