我试图了解动态分配的数组在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"和"不应该工作",而且,它适用 *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;
}
即成员可以容纳四个成员,每个成员可以容纳一个字符串的地址。
几件事:
- 对于您的第一个 malloc,
malloc(4*sizeof(*members))
,如果您要使用您尝试为其分配空间的对象类型会更清楚,例如malloc(4 * sizeof(char *))
而不是使用变量的名称。编辑:正如 CMASTER 所指出的,如果您更改变量的类型而不更改malloc()
中的类型,这可能会导致问题,因此请谨慎对待此建议 - 在您的情况下,
*members=malloc(5);
不是必需的,因为您的编译器已经为您分配了字符串"john"
的空间,并且 -
*members="john";
的工作原理是将字符串数组索引 0 处的指针设置为分配给"john"
的编译器的地址 - 同样,由于 3 中提到的一点,
*(members+1)="shouldn't work";
实际上确实有效。 - 最后,由于这一行 -
*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)
一起检查以识别指向数据的项目。