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 可以容纳四个成员,每个成员可以容纳一个字符串的地址。
几件事:
- 对于您的第一个 malloc,
malloc(4*sizeof(*members))
,如果您使用您尝试分配的对象的 类型 会更清楚 space 例如malloc(4 * sizeof(char *))
而不是使用变量名。 edit: 正如 cmaster 指出的那样,如果您更改变量的类型而不更改 malloc()
中的类型,这可能会导致问题,所以请对这个建议持保留态度
*members=malloc(5);
在您的情况下不是必需的,因为您的编译器已经为字符串 "john"
分配了 space ,并且
*members="john";
通过将字符串数组索引 0 处的 指针 设置为编译器分配的 地址 "john"
- 类似地,
*(members+1)="shouldn't work";
实际上确实有效,因为3. 中提到的一点
- 最后,由于这一行 --
*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)
以确定指向数据的项目。
我想了解动态分配的数组在 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 可以容纳四个成员,每个成员可以容纳一个字符串的地址。
几件事:
- 对于您的第一个 malloc,
malloc(4*sizeof(*members))
,如果您使用您尝试分配的对象的 类型 会更清楚 space 例如malloc(4 * sizeof(char *))
而不是使用变量名。 edit: 正如 cmaster 指出的那样,如果您更改变量的类型而不更改malloc()
中的类型,这可能会导致问题,所以请对这个建议持保留态度 *members=malloc(5);
在您的情况下不是必需的,因为您的编译器已经为字符串"john"
分配了 space ,并且*members="john";
通过将字符串数组索引 0 处的 指针 设置为编译器分配的 地址"john"
- 类似地,
*(members+1)="shouldn't work";
实际上确实有效,因为3. 中提到的一点
- 最后,由于这一行 --
*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)
以确定指向数据的项目。