将循环中的值赋给字符指针数组

时间:2012-11-07 13:51:26

标签: c arrays pointers char

我无法在循环中为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 个答案:

答案 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循环的局部变量,一旦循环结束,它就会超出范围。