Arrays 为什么for循环用最新的字符串填充整个数组?

Arrays 为什么for循环用最新的字符串填充整个数组?,arrays,c,pointers,cs50,implicit-conversion,Arrays,C,Pointers,Cs50,Implicit Conversion,如果这很简单,我很抱歉,但我是C语言的新手。我正在尝试创建一个循环,用多个字符串填充空字符串数组。但是,在最后,整个数组将被最新的元素填充!代码如下: int main(void) { string array_test[2]; char string_test[300]; for (int i = 0; i < 2; i++) { snprintf(string_test, sizeof(string_test),"Test:

如果这很简单,我很抱歉,但我是C语言的新手。我正在尝试创建一个循环,用多个字符串填充空字符串数组。但是,在最后,整个数组将被最新的元素填充!代码如下:

int main(void)
{
    string array_test[2];
    char string_test[300];

    for (int i = 0; i < 2; i++)
    {
        snprintf(string_test, sizeof(string_test),"Test: %i", i);
        array_test[i] = string_test;
    }

    for (int i = 0; i < 2; i++)
    {
        printf("%s\n", array_test[i]);
    }
}
但我期待着:

Test: 0
Test: 1

因为在所有迭代中使用相同的缓冲区来保存字符串。这将使以前的字符串被新字符串覆盖

为每个字符串分配单独的缓冲区以避免这种情况

/* put #include of required headers here */

int main(void)
{
    string array_test[2];
    char string_test[2][300];

    for (int i = 0; i < 2; i++)
    {
        snprintf(string_test[i], sizeof(string_test[i]),"Test: %i", i);
        array_test[i] = string_test[i];
    }

    for (int i = 0; i < 2; i++)
    {
        printf("%s\n", array_test[i]);
    }
}
/*put#在此处包含所需的标题*/
内部主(空)
{
字符串数组_测试[2];
字符串_检验[2][300];
对于(int i=0;i<2;i++)
{
snprintf(字符串测试[i],sizeof(字符串测试[i]),“测试:%i”,i);
数组_测试[i]=字符串_测试[i];
}
对于(int i=0;i<2;i++)
{
printf(“%s\n”,数组_测试[i]);
}
}
为什么for循环用最新的字符串填充整个数组

for循环用字符数组
string\u test
的第一个字符的地址填充整个指针数组

也就是说,您声明了一个由两个指针组成的数组

string array_test[2];
数组的每个元素都指向同一数组的第一个字符
string\u test

array_test[i] = string_test;
上面的陈述等同于下面的陈述

array_test[i] = &string_test[0];
这是表达式中使用的数组指示符,很少有例外,它被转换为指向其第一个元素的指针

因此,您使用两个指针输出相同的字符数组
string\u test

printf("%s\n", array_test[i]);
可以声明二维字符数组,而不是指针数组,如

char array_test[2][300];
在第一个for循环中,您可以将数组
string\u test
中形成的字符串复制到数组
array\u test
的元素中

strcpy( array_test[i], string_test );

在这种情况下,二维数组中的每个元素都将存储自己的字符串。

字符串数组中的所有元素都指向同一个缓冲区,因此它们看起来都具有相同的字符串,更准确地说是最后组成此缓冲区的值

char*
使用typedef
string
会造成对这一事实的混淆,这也是不在typedef后面隐藏指针的另一个原因

您可以在循环中分配字符串的副本:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char *array_test[2];
    char string_test[300];

    for (int i = 0; i < 2; i++) {
        snprintf(string_test, sizeof(string_test), "Test: %i", i);
        array_test[i] = strdup(string_test);
    }

    for (int i = 0; i < 2; i++) {
        printf("%s\n", array_test[i]);
    }

    for (int i = 0; i < 2; i++) {
        free(array_test[i]);
    }
    return 0;
}
#包括
#包括
#包括
int main(){
字符*数组_测试[2];
字符串_测试[300];
对于(int i=0;i<2;i++){
snprintf(字符串测试),sizeof(字符串测试),“测试:%i”,i;
数组测试[i]=strdup(字符串测试);
}
对于(int i=0;i<2;i++){
printf(“%s\n”,数组_测试[i]);
}
对于(int i=0;i<2;i++){
自由(数组_检验[i]);
}
返回0;
}

当然,在这种情况下,使用两个不同的数组没有多大意义。数组分配不会复制。每次只需将
array\u test[i]
设置为指向同一
string\u test
数组的指针。将
array\u test[0]
array\u test[1]
设置为
string\u test
,这本身就是一个字符串。由于您没有实际制作副本,
array\u test
的两个元素都指向同一个字符串,
string\u test
的最新更新如果您没有使用CS50
string
typedef,则会更加明显。什么是
string
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char *array_test[2];
    char string_test[300];

    for (int i = 0; i < 2; i++) {
        snprintf(string_test, sizeof(string_test), "Test: %i", i);
        array_test[i] = strdup(string_test);
    }

    for (int i = 0; i < 2; i++) {
        printf("%s\n", array_test[i]);
    }

    for (int i = 0; i < 2; i++) {
        free(array_test[i]);
    }
    return 0;
}