要消除混淆,您必须正确理解指针、数组和初始化程序。
C 编程初学者的一个常见误解是数组等同于指针。
数组是相同类型的项目的集合。考虑以下声明:
char arr[10];
此数组包含 10 个元素,每个元素的类型为 char。
可以使用初始化列表以方便的方式初始化数组。下面用初始化列表的对应值初始化数组元素:
char array[10] = {'a','b','c','d','e','f','g','h','i','\0'};
数组不可赋值,因此初始化列表的使用仅在数组声明时有效。
char array[10];
array = {'a','b','c','d','e','f','g','h','i','\0'}; // Invalid...
char array1[10];
char array2[10] = {'a','b','c','d','e','f','g','h','i','\0'};
array1 = array2; // Invalid...; You cannot copy array2 to array1 in this manner.
在数组声明之后,对数组成员的赋值必须通过数组索引操作符或其等价物。
char array[10];
array[0] = 'a';
array[1] = 'b';
.
.
.
array[9] = 'i';
array[10] = '\0';
循环是为数组成员赋值的一种常用且方便的方法:
char array[10];
int index = 0;
for(char val = 'a'; val <= 'i'; val++) {
array[index] = val;
index++;
}
array[index] = '\0';
char 数组可以通过字符串字面量进行初始化,这些字面量是常量以 null 结尾的 char 数组:
char array[10] = "abcdefghi";
但以下内容无效:
char array[10];
array = "abcdefghi"; // As mentioned before, arrays are not assignable
现在,让我们来看看指针...
指针是可以存储另一个变量的地址的变量,通常是相同的类型。
考虑以下声明:
char *ptr;
这声明了一个char * 类型的变量,一个char 指针。也就是可能指向char 变量的指针。
与数组不同,指针是可赋值的。因此以下是有效的:
char var;
char *ptr;
ptr = &var; // Perfectly Valid...
由于指针不是数组,因此只能为指针分配一个值。
char var;
char *ptr = &var; // The address of the variable `var` is stored as a value of the pointer `ptr`
回想一下,必须为指针分配一个值,因此以下内容无效,因为初始化器的数量不止一个:
char *ptr = {'a','b','c','d','\0'};
这是违反约束的,但您的编译器可能只是将 'a' 分配给 ptr 并忽略其余部分。但即便如此,编译器也会警告您,因为 'a' 等字符文字默认具有 int 类型,并且与 ptr 的类型不兼容,即 char *。
如果这个指针在运行时被取消引用,那么它会导致访问无效内存的运行时错误,导致程序崩溃。
在你的例子中:
char *str = {"what", "is", "this"};
同样,这是违反约束的,但您的编译器可能会将字符串 what 分配给 str 并忽略其余部分,并仅显示警告:
warning: excess elements in scalar initializer.
现在,这是我们消除关于指针和数组的混淆的方法:
在某些情况下,数组可能会衰减为指向数组第一个元素的指针。因此以下是有效的:
char arr[10];
char *ptr = arr;
通过在赋值表达式中使用数组名称arr 作为rvalue,数组衰减为指向它的第一个元素的指针,这使得前面的表达式等效于:
char *ptr = &arr[0];
记住arr[0]的类型是char,&arr[0]是它的地址,类型是char *,与变量ptr兼容。
回想一下,字符串文字是常量以 null 结尾的 char 数组,因此以下表达式也是有效的:
char *ptr = "abcdefghi"; // the array "abcdefghi" decays to a pointer to the first element 'a'
现在,在您的情况下,char str[][5] = {"what","is","this"}; 是一个由 3 个数组组成的数组,每个数组包含 5 个元素。
由于数组不可赋值,str[i] = "newstring"; 无效,因为 str[i] 是数组,但 str[i][j] = 'j'; 有效,因为
str[i][j] 是一个数组元素,它本身不是一个数组,并且是可赋值的。