我无法在循环中为char数组赋值,在每个数组值中包含相同的值
例如,这可行
char* foo[3];
foo[0] = "mango"; foo[1] = "kiwi"; foo[2] = "banana";
int i=0; for(i=0;i<3;i++)
{
printf("%s\n",foo[i]);
}
但这不是,我不明白为什么。
char* foo[3]; int i=0;
for(i=0;i<3;i++) {
char temp[5];
sprintf(temp,"VAL:%d",i);
foo[i] = temp;
}
for(i=0;i<3;i++)
{
printf("%s\n",foo[i]);
}
请提前帮助和感谢
答案 0 :(得分:3)
第二个片段中的问题是foo
中的所有元素都指向同一个变量temp
,当执行第二个for
时,该变量超出了范围,这是未定义的行为。即使它不在范围之外,foo
中的所有元素都会指向同一个不正确的缓冲区。
要更正,您需要复制temp
并将其存储在foo
的每个元素中。这可以通过使用strdup()
(如果可用)(如果不是malloc()
和strcpy()
)来实现:
for (i = 0; i < sizeof(foo)/sizeof(foo[0]); i++)
{
char temp[6];
snprintf(temp, sizeof(temp), "VAL:%d", i);
foo[i] = strdup(temp); /* Must be free()d later. */
}
或更改foo
的类型(已由unwind建议):
char foo[3][6];
int i;
for (i = 0; i < sizeof(foo)/sizeof(foo[0]);i++)
{
snprintf(foo[i], sizeof(foo[i]), "VAL:%d", i);
}
其他变化:
temp
的大小增加到6
,因为它需要5
个字符VAL:%d
加上 {{1}附加的空终结符}。由于这个原因,发布的代码有一个缓冲区溢出。snprintf()
来避免缓冲区溢出。sprintf()
计算数组sizeof(foo)/sizeof(foo[0])
中的元素数,而不是对元素数进行硬编码。答案 1 :(得分:2)
您必须记住,在C中,char*
实际上并不存储字符串,但它存储了将被视为字符串的第一个字符的内存位置的地址。
在第一个示例中,foo
数组的每个元素都包含不同字符串文字的地址。
在第二个示例中,foo
数组的每个元素都指向局部变量temp
。虽然通过循环的每次迭代都会产生一个单独的temp
实例,但任何理智的编译器都会将所有这些实例放在彼此之上,从而给出您所经历的结果。
解决方案是使用2D数组:
char foo[3][6]; int i=0;
for (i=0; i<3; i++) { sprintf(foo[i],"VAL:%d", i); }
for (i=0; i<3; i++) { printf("%s\n", foo[i]); }
或者使用动态分配:
char* foo[3]; int i=0;
for (i=0; i<3; i++) { char* temp = malloc(6); sprintf(temp, "VAL:%d", i); foo[i] = temp; }
for (i=0; i<3; i++) { printf("%s\n", foo[i]); free(foo[i]); }
答案 2 :(得分:0)
循环中的temp
变量可能在每次迭代时重复使用相同的内存,因此您最终会将相同的地址写入每个foo[]
插槽。然后,更糟糕的是,当您退出循环时,该地址无法访问,从而导致未定义的行为。
您需要动态分配每个字符串,或者使用带空格的字符串数组作为实际字符串(char foo[3][20];
或其他内容)。
答案 3 :(得分:0)
两个问题:
1)您已将temp
声明为char temp[5]
,并且您填充的内容超过4个字符:
sprintf(temp,"VAL:%d",i);
导致sprintf写入数组末尾,因为它必须写入终止\0
2)变量temp
是for循环的局部变量,一旦循环结束,它就会超出范围。