when defining a C string, aka char array, by double quotations "...", in the format below:
char * <varName> = "<someString>"
only the elements of the array are immutable (their content can not be changed). In other words, the <varName> has a const char * type (a mutable pointer towards a read-only memory). And every time you invoke the assignment operator with double quotations <varName> = "<otherString>" it changes the pointer value automatically. The below example should give a complete overview of the different possibilities:
#include <stdio.h>
int main()
{
char * var_1 = "Lorem";
printf("1. %s , %p\n", var_1, var_1); // --> 1. Lorem , 0x400640
var_1 = "ipsu";
printf("2. %s , %p\n", var_1, var_1); // --> 2. ipsu , 0x400652
// var_1[0] = 'x'; // --> Segmentation fault
var_1++;
printf("3. %s , %p\n", var_1, var_1); // --> 3. psu , 0x400653
char var_2[] = {'L', 'o', 'r', 'e', 'm', '\0'};
printf("4. %s , %p\n", var_2, var_2); // --> 4. Lorem , 0x7ffed0fc5381
var_2[0] = 'x';
printf("5. %s , %p\n", var_2, var_2); // --> 5. xorem , 0x7ffed0fc5381
// var_2++; //error: lvalue required as increment operand
char var_3[] = "Lorem";
printf("6. %s , %p\n", var_3, var_3); // --> 6. Lorem , 0x7ffe36a42d5c
// var_3 = "ipsu"; // --> error: assignment to expression with array type
var_3[0] = 'x';
printf("7. %s , %p\n", var_3, var_3); // --> 7. xorem , 0x7ffe36a42d5c
char * const var_4 = "Lorem";
// var_4 = "ipsu"; // --> error: assignment of read-only variable
// var_4[0] = 'x'; // --> Segmentation fault
char const * var_5 = "Lorem";
printf("8. %s , %p\n", var_5, var_5); // --> Lorem , 0x400720
var_5 = "ipsu";
printf("9. %s , %p\n", var_5, var_5); // --> ipsu , 0x400732
// var_5[0] = 'x'; // --> error: assignment of read-only location
const char * var_6 = "Lorem";
printf("10. %s , %p\n", var_6, var_6); // --> 10. Lorem , 0x400760
var_6 = "ipsu";
printf("11. %s , %p\n", var_6, var_6); // --> 11. ipsu , 0x400772
// var_6[0] = 'x'; // --> error: assignment of read-only location
const char const * var_7 = "Lorem"; // clang only --> warning: duplicate 'const' declaration specifier [-Wduplicate-decl-specifier]
printf("12. %s , %p\n", var_7, var_7); // --> 12. Lorem , 0x400760
var_7 = "ipsu";
printf("13. %s , %p\n", var_7, var_7); // --> 13. ipsu , 0x400772
// var_7[0] = 'x'; // --> error: assignment of read-only location
char const const * var_8 = "Lorem"; // clang only --> warning: duplicate 'const' declaration specifier [-Wduplicate-decl-specifier]
printf("14. %s , %p\n", var_8, var_8); // --> 14. Lorem , 0x400790
var_8 = "ipsu";
printf("15. %s , %p\n", var_8, var_8); // --> 15. ipsu , 0x4007a2
// var_8[0] = 'x'; // --> error: assignment of read-only location
char const * const var_9 = "Lorem";
// var_9 = "ipsu"; // --> error: assignment of read-only variable
// var_9[0] = 'x'; // --> error: assignment of read-only location
const char var_10[] = {'L', 'o', 'r', 'e', 'm', '\0'};
// var_10[0] = 'x'; // --> error: assignment of read-only location
// var_10++; // --> error: lvalue required as increment operand
char const var_11[] = {'L', 'o', 'r', 'e', 'm', '\0'};
// var_11[0] = 'x'; // --> error: assignment of read-only location
// var_11++; // --> error: lvalue required as increment operand
const char var_12[] = "Lorem";
// var_12[0] = 'x'; // --> error: assignment of read-only location
// var_12++; // --> error: lvalue required as increment operand
char const var_13[] = "Lorem";
// var_13[0] = 'x'; // --> error: assignment of read-only location
// var_13++; // --> error: lvalue required as increment operand
return 0;
}
this code was tested on GCC, Clang and Visual Studio.
Basically, there are three possibilities:
immutable pointer, mutable content
char <varName>[] = {'L', 'o', 'r', 'e', 'm', '\0'};
char <varName>[] = "Lorem";
mutable pointer, immutable content
char * <varName> = "Lorem";
char const * <varName> = "Lorem";
const char * <varName> = "Lorem";
const char const * <varName> = "Lorem";
char const const * <varName> = "Lorem";
immutable pointer, immutable content
char * const <varName> = "Lorem";
char const * const <varName> = "Lorem";
const char * const <varName> = "Lorem";
const char <varName>[] = {'L', 'o', 'r', 'e', 'm', '\0'};
char const <varName>[] = {'L', 'o', 'r', 'e', 'm', '\0'};
const char <varName>[] = "Lorem";
char const <varName>[] = "Lorem";
Conclusion:
<typing> <varName>[] = <string> always returns an immutable pointer and the mutability of the content is independant from the <array> format ("Lorem" or {'L', 'o', 'r', 'e', 'm', '\0'})
<typing> * <varName> = "someString" always returns immutable content
<typing> * const <varName> = "someString" always returns both immutable content and pointer
char const <other>, char const <other>, const char const <other>, and char const const <other> always create immutable content.
I have tried to summerise C's array behavior here in detail.