0

我不能在循环中为 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]); 
}

请提前帮助和感谢

4

4 回答 4

3

第二个片段中的问题是所有元素都foo指向同一个变量 ,temp当第二个片段被执行时,它超出了范围for,这是未定义的行为。即使它没有超出范围,所有元素foo都会指向相同的缓冲区,这是不正确的。

要更正,您需要制作副本temp并将其存储在foo. 这可以通过使用strdup()if available (如果不是malloc()and 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);
}

其他变化:

  • 增加 to 的大小,temp因为6它需要5字符VAL:%d 加上.附加的空终止符sprintf()。因此,发布的代码有缓冲区溢出。
  • 使用snprintf()以避免缓冲区溢出。
  • 使用sizeof(foo)/sizeof(foo[0])来计算数组中的元素数量,foo而不是对元素数量进行硬编码。
于 2012-11-07T13:53:20.483 回答
2

您必须记住,在 C 中,achar*实际上并不存储字符串,而是存储将被视为字符串的第一个字符的内存位置的地址。

在您的第一个示例中,数组的每个元素都foo包含不同字符串文字的地址。在您的第二个示例中,数组的每个元素都foo指向局部变量temp。尽管循环中的每次迭代都会产生一个单独的实例temp,但任何理智的编译器都会将所有这些实例放在彼此之上,从而提供您所体验的结果。

解决方案是使用二维数组:

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]); }
于 2012-11-07T14:04:54.920 回答
0

循环中的temp变量可能在每次迭代中重复使用相同的内存,因此您最终将相同的地址写入每个foo[]插槽。然后,更糟糕的是,当您退出循环时,该地址变得无法访问,从而导致未定义的行为。

您需要动态分配每个字符串,或者使用带有空间的字符串数组来存储实际字符串(char foo[3][20];或其他内容)。

于 2012-11-07T13:54:32.943 回答
0

两个问题:

1)您已声明tempchar temp[5]并且您正在填充超过 4 个字符:

sprintf(temp,"VAL:%d",i);

在那里通过导致 sprintf 写入超出数组的末尾,因为它必须写入终止\0

2) 该变量temp是 for 循环的本地变量,一旦循环结束,它就会超出范围。

于 2012-11-07T13:54:33.450 回答