Case 1:
When I write
char*str={"what","is","this"};
then str[i]="newstring";
is valid whereas str[i][j]='j';
is invalid.
Part I.I
>> char*str={"what","is","this"};
In this statement, str
is a pointer to char
type.
When compiling, you must be getting a warning message on this statement:
warning: excess elements in scalar initializer
char*str={"what","is","this"};
^
Reason for the warning is - You are providing more than one initializer to a scalar.
[Arithmetic types and pointer types are collectively called scalar types.]
str
is a scalar and from C Standards#6.7.9p11:
The initializer for a scalar shall be a single expression, optionally enclosed in braces. ..
Furthermore, giving more than one initializer to a scalar is undefined behavior.
From C Standards#J.2 Undefined behavior:
The initializer for a scalar is neither a single expression nor a single expression enclosed in braces
Since it is undefined behavior as per the standard, there is no point in discussing it further. Discussing Part I.II and Part I.III with an assumption - char *str="somestring"
, just for better understanding of char *
type.
Seems that you want to create an array of pointers to string. I have added a brief about the array of pointers to string, below in this post, after talking about both the cases.
Part I.II
>> then str[i]="newstring"; is valid
No, this is not valid.
Again, the compiler must be giving a warning message on this statement because of incompatible conversion.
Since str
is a pointer to char
type. Therefore, str[i]
is a character at i
places past the object pointed to by str
[str[i] --> *(str + i)
].
"newstring"
is a string literal and a string literal decays into a pointer, except when used to initialize an array, of type char *
and here you are trying to assign it to a char
type. Hence the compiler reporting it as a warning.
Part I.III
>> whereas str[i][j]='j'; is invalid.
Yes, this is invalid.
The []
(subscript operator) can be used with array or pointer operands.
str[i]
is a character and str[i][j]
means you are using []
on char
operand which is invalid. Hence the compiler reporting it as an error.
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.
Part II.I
>> char str[][5]={"what","is","this"};
This is absolutely correct.
Here, str
is a 2D-array. Based on the number of initializers, the compiler will automatically set the first dimension.
The in-memory view of str[][5]
, in this case, would be something like this:
str
+-+-+-+-+-+
str[0] |w|h|a|t|0|
+-+-+-+-+-+
str[1] |i|s|0|0|0|
+-+-+-+-+-+
str[2] |t|h|i|s|0|
+-+-+-+-+-+
Based on initializer list, the respective elements of 2D-array will be initialized and the rest of the elements are set to 0
.
Part II.II
>> then str[i]="newstring"; is not valid
Yes, this is not valid.
str[i]
is a one-dimensional array.
As per the C Standards, an array is not a modifiable lvalue.
From C Standards#6.3.2.1p1:
An lvalue is an expression (with an object type other than void) that potentially designates an object;64) if an lvalue does not designate an object when it is evaluated, the behavior is undefined. When an object is said to have a particular type, the type is specified by the lvalue used to designate the object. A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const- qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const- qualified type.
Also, an array name convert to pointer that point to initial element of the array object except when it is the operand of the sizeof operator, the _Alignof operator or the unary & operator.
From C Standards#6.3.2.1p3:
Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ''array of type'' is converted to an expression with type ''pointer to type'' that points to the initial element of the array object and is not an lvalue.
Since str
is already initialized and when you assign some other string literal to i
th array of str
, the string literal convert to a pointer which makes the assignment incompatible because you have lvalue of type char
array and rvalue of type char *
. Hence the compiler reporting it as an error.
Part II.III
>> whereas str[i][j]='J'; is valid.
Yes, this is valid as long as the i
and j
are valid values for given array str
.
str[i][j]
is of type char
, so you can assign a character to it.
Beware, C does not check array boundaries and accessing an array out of bounds is undefined behavior which includes - it may fortuitously do exactly what the programmer intended or segmentation fault or silently generating incorrect results or anything can happen.
Assuming that in the Case 1, you want to create an array of pointers to string.
It should be like this:
char *str[]={"what","is","this"};
^^
The in-memory view of str
will be something like this:
str
+----+ +-+-+-+-+--+
str[0]| |--->|w|h|a|t|\0|
| | +-+-+-+-+--+
+----+ +-+-+--+
str[1]| |--->|i|s|\0|
| | +-+-+--+
+----+ +-+-+-+-+--+
str[2]| |--->|t|h|i|s|\0|
| | +-+-+-+-+--+
+----+
"what"
, "is"
and "this"
are string literals.
str[0]
, str[1]
and str[2]
are pointers to the respective string literal and you can make them point to some other string as well.
So, this is perfectly fine:
str[i]="newstring";
Assuming i
is 1, so str[1]
pointer is now pointing to string literal "newstring"
:
+----+ +-+-+-+-+-+-+-+-+-+--+
str[1]| |--->|n|e|w|s|t|r|i|n|g|\0|
| | +-+-+-+-+-+-+-+-+-+--+
+----+
But you should not do this:
str[i][j]='j';
(assuming i=1
and j=0
, so str[i][j]
is first character of second string)
As per the standard attempting to modify a string literal results in undefined behavior because they may be stored in read-only storage or combined with other string literals.
From C standard#6.4.5p7:
It is unspecified whether these arrays are distinct provided their elements have the appropriate values. If the program attempts to modify such an array, the behavior is undefined.
Additional:
There is no native string type in C language. In C language, a string is a null-terminated array of characters. You should know the difference between arrays and pointers.
I would suggest you read following for better understanding about arrays, pointers, array initialization:
- Array Initialization, check this.
- Equivalence of pointers and arrays, check this and this.