char*str={quot;foo";,…}和char-str[][5]={quot;foo";,…}数组定义之间有什么区别?
案例1:当我写作时char*str={quot;foo";,…}和char-str[][5]={quot;foo";,…}数组定义之间有什么区别?,c,arrays,pointers,arrayofarrays,C,Arrays,Pointers,Arrayofarrays,案例1:当我写作时 char*str={"what","is","this"}; char str[][5]={"what","is","this"}; char*str={"what","is","this"}; char str[][5]={"what","is","this"}; 然后str[i]=“newstring”有效,而str[i][j]='j'无效 案例
char*str={"what","is","this"};
char str[][5]={"what","is","this"};
char*str={"what","is","this"};
char str[][5]={"what","is","this"};
然后str[i]=“newstring”代码>有效,而str[i][j]='j'代码>无效
案例2:当我写作时
char*str={"what","is","this"};
char str[][5]={"what","is","this"};
char*str={"what","is","this"};
char str[][5]={"what","is","this"};
然后str[i]=“newstring”代码>无效,而str[i][j]='j'代码>是有效的
为什么会这样?我是一个初学者,在阅读了其他答案后已经感到非常困惑。首先定义一个变量,该变量是指向字符的指针,通常仅用作单个字符串。它初始化指针以指向字符串文本“what”
。编译器还应该抱怨列表中的初始值设定项太多
第二个定义是str
一个由三个数组组成的数组,每个数组有五个char
。也就是说,它是一个由三个五个字符串组成的数组
稍有不同的是,可以这样看:
str
+-+-+-+-+-+
str[0] |w|h|a|t|0|
+-+-+-+-+-+
str[1] |i|s|0|0|0|
+-+-+-+-+-+
str[2] |t|h|i|s|0|
+-+-+-+-+-+
char *str[]={"what","is","this"};
^^
str
+----+ +-+-+-+-+--+
str[0]| |--->|w|h|a|t|\0|
| | +-+-+-+-+--+
+----+ +-+-+--+
str[1]| |--->|i|s|\0|
| | +-+-+--+
+----+ +-+-+-+-+--+
str[2]| |--->|t|h|i|s|\0|
| | +-+-+-+-+--+
+----+
对于第一种情况:
+-----+ +--------+
| str | --> | "what" |
+-----+ +--------+
+-----+ +--------+
|str |-->|“什么”|
+-----+ +--------+
这是你的第二次
+--------+--------+--------+
| "what" | "is" | "this" |
+--------+--------+--------+
+--------+--------+--------+
|“这是什么?”|
+--------+--------+--------+
还请注意,对于第一个版本,当指针指向单个字符串时,表达式str[i]=“newstring”
也会导致警告,因为您试图将指针分配给单个char
元素
该赋值在第二个版本中也是无效的,但另一个原因是:str[i]
是一个数组(由五个char
元素组成),不能赋值给数组,只能复制给它。因此,您可以尝试执行strcpy(str[i],“newstring”)
,编译器不会抱怨。但这是错误的,因为您试图将10个字符(记住终止符)复制到一个5个字符的数组中,这将导致写越界,导致未定义的行为。首先:建议:请阅读强>
也就是说,为了启发这个特定的场景
- 在第一种情况下
char*str={"what","is","this"};
不会做你认为它会做的事。根据第§6.7.9/P2章,这是一种违反约束的行为,需要任何符合C的实施进行诊断:
初始化者不得试图为实体中不包含的对象提供值
正在初始化
如果启用警告,您(至少)会看到
警告:标量初始值设定项中的元素过多
char*str={"what","is","this"};
但是,启用了严格一致性的(ny)编译器应该拒绝编译代码。在这种情况下,编译器选择编译并生成二进制代码,其行为不在C语言定义的范围内,而是由编译器实现决定(因此,可以有很大的差异)
在本例中,编译器决定此语句在功能上仅与char*str=“what”相同代码>
因此,这里的str
是指向char
的指针,它指向一个字符串文本。
您可以重新分配给指针
str="newstring"; //this is valid
但是,像这样的声明
str[i]="newstring";
str[i][j]='J'; // compiler error
将是无效的,因为此处尝试将指针类型转换并存储为char
类型,其中类型不兼容。在这种情况下,编译器应该抛出关于无效转换的警告
此后,一份声明如
str[i]="newstring";
str[i][j]='J'; // compiler error
在语法上无效,因为您在非“指向完整对象类型的指针”的对象上使用数组订阅[]
运算符,如
- 另一方面,在第二种情况下
char*str={"what","is","this"};
str
是一个数组数组。您可以更改单个数组元素
str[i][j]='J'; // change individual element, good to go.
但是您不能分配给数组
str[i]="newstring"; // nopes, array type is not an lvalue!!
- 最后,
char str[][5]={"what","is","this"};
在第一种情况下,数组的逻辑相同。这使得str
成为一个指针数组。数组成员是可分配的
str[i]="newstring"; // just overwrites the previous pointer
完全可以。但是,作为数组成员存储的指针是指向字符串文字的指针,因此出于上述相同的原因,当您想要修改属于字符串文字的内存元素之一时,可以调用
str[i][j]='j'; //still invalid, as above.
- 在第一次声明中
char *str={"what","is","this"};
声明str
指向char
的指针,是标量。标准上说
6.7.9初始化(第11页):
标量的初始值设定项应为单个表达式,可以选择用大括号括起来。[……]
也就是说,标量类型可以有大括号括起来的初始值设定项,但只有一个表达式,但在
char *str = {"what","is","this"}; // three expressions in brace enclosed initializer
它将如何处理这个问题取决于编译器。请注意,其他初始值设定项发生的情况是一个错误。确认编译器应给出诊断信息
[Warning] excess elements in scalar initializer
5.1.1.3诊断(P1):
如果预处理翻译单元或翻译单元包含违反任何语法规则或约束的行为,即使行为也明确指定为未定义或实现定义,一致性实现应产生至少一条诊断消息(以实现定义的方式识别)
- 您声明“
str[i]=“newstring”
有效,而str[i][j]=“j”;
无效
str[i]
属于char
类型,只能保存char
数据类型。分配“newstring”
(属于char*
)无效。语句str[i][j]='j'代码>无效,因为下标运算符只能应用于数组或指针数据类型
- 您可以使
str[i]=“newstring”代码>通过将str
声明为char*
char *str[] = {"what","is","this"};
在这种情况下,str[i]
属于char*
类型,可以为其分配字符串文字,但修改字符串文字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 array[10] = "abcdefghi";
char array[10];
array = "abcdefghi"; // As mentioned before, arrays are not assignable
char *ptr;
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'};
char *str = {"what", "is", "this"};
char arr[10];
char *ptr = arr;
char *ptr = &arr[0];
char *ptr = "abcdefghi"; // the array "abcdefghi" decays to a pointer to the first element 'a'
char*str={"what","is","this"};
char*str={"what","is","this"};
warning: excess elements in scalar initializer
char*str={"what","is","this"};
^
char str[][5]={"what","is","this"};
str
+-+-+-+-+-+
str[0] |w|h|a|t|0|
+-+-+-+-+-+
str[1] |i|s|0|0|0|
+-+-+-+-+-+
str[2] |t|h|i|s|0|
+-+-+-+-+-+
char *str[]={"what","is","this"};
^^
str
+----+ +-+-+-+-+--+
str[0]| |--->|w|h|a|t|\0|
| | +-+-+-+-+--+
+----+ +-+-+--+
str[1]| |--->|i|s|\0|
| | +-+-+--+
+----+ +-+-+-+-+--+
str[2]| |--->|t|h|i|s|\0|
| | +-+-+-+-+--+
+----+
str[i]="newstring";
+----+ +-+-+-+-+-+-+-+-+-+--+
str[1]| |--->|n|e|w|s|t|r|i|n|g|\0|
| | +-+-+-+-+-+-+-+-+-+--+
+----+
str[i][j]='j';
char*str={"what","is","this"};
char str[][5]={"what","is","this"};