C中动态分配的字符串数组

Dynamically allocated string arrays in C

我想了解动态分配的数组在 C 99 中是如何工作的。无论如何,我有以下代码:

int main()
{
    char** members=malloc(4*sizeof(*members));
    *members=malloc(5);
    *members="john";
    *(members+1)="shouldn't work";
    printf("%s \n",*members);
    printf("%s",*(members+1));
    return 0;
}

我以为我会得到一个 运行 时间错误,因为我没有分配 (members+1),但实际上它打印了 "john" 和 "shouldn't work",另外,它似乎不需要 *members=malloc(5) 行。为什么?

您的作业没有按照您认为的那样进行。当您分配 *members*(members+1) 时,您是将 char* 分配给每个字符串文字,而不是将其复制到已分配(或未分配)的堆内存中。

如果您将作业替换为 strcpy,即:

strcpy(*members, "john");
strcpy(*(members+1), "shouldn't work");

那么您将在第二次分配时遇到访问冲突,但不会在第一次分配时发生。同样, malloc(5) 似乎不必要的原因是因为您将指针重新分配为指向字符串文字,而不是将 "john" 字符串复制到分配的内存中。

char** members=malloc(4*sizeof(*members));

这意味着你已经创建了一个数组并为四个元素分配了内存,可以存储一个字符串的地址。

因此,如果您删除行 *members=malloc(5);那么它也会起作用。

int main()
{
char** members=malloc(4*sizeof(*members));
//*members=malloc(5);
*members="john";
*(members+1)="shouldn't work";
printf("%s \n",*members);
printf("%s",*(members+1));
return 0;
}

即member 可以容纳四个成员,每个成员可以容纳一个字符串的地址。

几件事:

  1. 对于您的第一个 malloc,malloc(4*sizeof(*members)),如果您使用您尝试分配的对象的 类型 会更清楚 space 例如malloc(4 * sizeof(char *)) 而不是使用变量名。 edit: 正如 cmaster 指出的那样,如果您更改变量的类型而不更改 malloc() 中的类型,这可能会导致问题,所以请对这个建议持保留态度
  2. *members=malloc(5); 在您的情况下不是必需的,因为您的编译器已经为字符串 "john" 分配了 space ,并且
  3. *members="john"; 通过将字符串数组索引 0 处的 指针 设置为编译器分配的 地址 "john"
  4. 类似地,*(members+1)="shouldn't work";实际上确实有效,因为3.
  5. 中提到的一点
  6. 最后,由于这一行 -- *members="john"; -- 你丢失了指向你 malloc(5) 的内存的指针,因此内存将被泄漏 :)

因为你已经用 4*sizeof(*members) 初始化了 char** 类型的指针我认为你打算存储 4 个字符串,所以建议为所有 4 个字符串分配内存,例如:

char** members=malloc(4*sizeof(*members));
int i;
for(i = 0; i < 4; i++)
    members[i] = malloc(100 + 1);  // 100 is a max length of string
              // actually length of each string can be different

或者您可以使用 NULL 初始化所有指针并根据需要更改它们(分配或指向一些已分配的内存),例如:

char** members=malloc(4*sizeof(*members));
int i;
for(i = 0; i < 4; i++)
    members[i] = NULL;  
// ... somewhere ....
char str[] = "Some string";
members[2] = str;
// ... somewhere else ....
members[1] = malloc(20);
scanf("%19s", members[1]); 

在这种情况下,您可以检查 if(members[i] != NULL) 以确定指向数据的项目。