Search code examples
carrayspointersarrayofarrays

What is the difference between char*str={"foo",...} and char str[][5]={"foo",...} array definitions?


Case 1: When I write

char*str={"what","is","this"};

then str[i]="newstring"; is valid whereas str[i][j]='j'; is invalid.

Case 2: When I write

char str[][5]={"what","is","this"};

then str[i]="newstring"; is not valid whereas str[i][j]='J'; is valid.

Why is it so? I am a beginner who already get very confused after reading the other answers.


Solution

  • First of all: A suggestion: Please read about arrays are not pointers and vice-versa!!

    That said, to enlighten this particular scenario,

    • In the first case,

      char*str={"what","is","this"};
      

      does not do what you think it does. It is a constraint violation, requiring a diagnostic from any conforming C implementation, as per chapter§6.7.9/P2:

      No initializer shall attempt to provide a value for an object not contained within the entity being initialized.

      If you enable warnings, you'd (at least) see

      warning: excess elements in scalar initializer

        char*str={"what","is","this"};
      

      However, a(ny) compiler with strict conformance turned on, should refuse to compile the code. In case, the compiler chose to compile and produce a binary anyway, the behavior is not withing the scope of definition of C language, it's up to the compiler implementation (and thus, can vary widely).

      In this case, compiler decided this statement to make functionally only same as char*str= "what";

      So, here str is a pointer to a char, which points to a string literal. You can re-assign to the pointer,

      str="newstring";  //this is valid
      

      but, a statement like

       str[i]="newstring";
      

      would be invalid, as here, a pointer type is attempted to be converted and stored into a char type, where the types are not compatible. The compiler should throw a warning about the invalid conversion in this case.

      Thereafter, a statement like

      str[i][j]='J'; // compiler error
      

      is syntactically invalid, as you're using the Array subscripting [] operator on something which is not "pointer to complete object type", like

      str[i][j] = ...
            ^^^------------------- cannot use this
      ^^^^^^ --------------------- str[i] is of type 'char', 
                                   not a pointer to be used as the operand for [] operator.
      
    • On the other hand, in second case,

      str is an array of arrays. You can change individual array elements,

       str[i][j]='J'; // change individual element, good to go.
      

      but you cannot assign to an array.

       str[i]="newstring";  // nopes, array type is not an lvalue!!
      

    • Finally, considering you meant to write (as seen in comments)

      char* str[ ] ={"what","is","this"};
      

      in your first case, the same logic for arrays hold. This makes str an array of pointers. So, the array members, are assignable, so,

      str[i]="newstring";  // just overwrites the previous pointer
      

      is perfectly OK. However, the pointers, which are stored as array members, are pointers to string literal, so for the very same reason mentioned above, you invoke undefined behavior, when you want to modify one of the elements of the memory belonging to the string literal

       str[i][j]='j';   //still invalid, as above.