结构指针的动态数组——我真的需要为 ea 元素显式分配 space 吗?
Dynamic array of pointer to structs - do I really need to explicitly allocate space for ea element?
我有一个这样定义的结构:
typedef struct
{
int num;
char letter;
}* Foo;
像这样的数组:
Foo* items = malloc(sizeof(Foo) * 4);
根据我的理解和这个问题的(已接受的)答案 Dynamic array of pointers to structs,我希望上面的行只为 4 个 Foo 项目保留内存,但不会初始化它 - 即,如果我尝试访问 items[i]->num
,应该会出现某种错误。
另外,为了将项目插入到这个数组中,我应该这样做:
items[0] = malloc(sizeof(*items[0]));
然而,我做了一点测试,似乎下面的代码打印 1
和 a
就好了:
Foo* items = malloc(sizeof(Foo) * 2);
items[0]->num = 4;
items[0]->letter = 'a';
printf("items[0] = {num=%d, char=%c}\n", items[0]->num, items[0]->letter);
我很困惑。这是预期的行为吗?
发生这种情况是因为您为 Foo
数组和可能的一个元素预留了足够的 space 但这不是预期的行为,在这种情况下没有预期的行为,因为您所做的调用未定义的行为。
如果向结构中添加更多字段,这将失败,因为那样 2 * sizeof(void *)
就不够了。要测试它,请尝试像这样向结构添加 2 个指针1
typedef struct
{
int num;
char letter;
void *pointers[2];
} *Foo;
如果你愿意,你可以做对,这是另一个原因 不 typedef
一个指针 ,这会起作用
typedef struct
{
int num;
char letter;
void *pointers[2];
} Foo;
Foo *foo_pointer = malloc(N * sizeof(Foo));
/* ^ this would be wrong if `Foo' were a pointer */
if (foo_pointer == NULL)
please_abort_this_do_not_continue_because_malloc_has_failed();
foo_pointer[0].num = 1;
foo_pointer[0].letter = 'a';
1写这个真的很烦我,因为typedef
指针从来都不是一个好主意
如果您想使用结构,您必须分配结构并将其指针保存到 items
的元素。否则,item
的元素是垃圾,访问它可能会导致错误。
由于删除了 malloc
并将 items[0]->num
和 items[0]->letter
的值直接传递给 printf
.[=16= 的优化,第二个测试可能工作正常]
您的初始 malloc:
Foo* items = malloc(sizeof(Foo) * 4);
正在创建一个包含 4 个指针的数组,因为 Foo
是指针类型。所以你的第二个 malloc:
items[0] = malloc(sizeof(*items[0]));
有道理,因为您正在为该指针分配一个结构。
但是,您正在执行的分配会导致未定义的行为,因为您没有执行第二个 malloc
,因此尚未将 space 分配给 items[0]
。 C 不会阻止您写入不应该写入的内存位置。一旦你这样做,任何事情都可能发生。
这里有点令人困惑的一件事是您使用 typedef
来定义指针类型。这可能会导致很多混乱,因为通过查看它是指针的类型并不明显。在这种情况下,由于您定义 Foo
的方式,您可能不需要额外的指针间接层。
因此,如果您这样定义结构:
typedef struct
{
int num;
char letter;
} Foo;
那么这就可以安全地完成了:
Foo* items = malloc(sizeof(Foo) * 2);
items[0].num = 4;
items[0].letter = 'a';
printf("items[0] = {num=%d, char=%c}\n", items[0].num, items[0].letter);
现在 malloc 创建结构数组而不是结构指针数组,因此不再需要额外的 malloc 层。
我有一个这样定义的结构:
typedef struct
{
int num;
char letter;
}* Foo;
像这样的数组:
Foo* items = malloc(sizeof(Foo) * 4);
根据我的理解和这个问题的(已接受的)答案 Dynamic array of pointers to structs,我希望上面的行只为 4 个 Foo 项目保留内存,但不会初始化它 - 即,如果我尝试访问 items[i]->num
,应该会出现某种错误。
另外,为了将项目插入到这个数组中,我应该这样做:
items[0] = malloc(sizeof(*items[0]));
然而,我做了一点测试,似乎下面的代码打印 1
和 a
就好了:
Foo* items = malloc(sizeof(Foo) * 2);
items[0]->num = 4;
items[0]->letter = 'a';
printf("items[0] = {num=%d, char=%c}\n", items[0]->num, items[0]->letter);
我很困惑。这是预期的行为吗?
发生这种情况是因为您为 Foo
数组和可能的一个元素预留了足够的 space 但这不是预期的行为,在这种情况下没有预期的行为,因为您所做的调用未定义的行为。
如果向结构中添加更多字段,这将失败,因为那样 2 * sizeof(void *)
就不够了。要测试它,请尝试像这样向结构添加 2 个指针1
typedef struct
{
int num;
char letter;
void *pointers[2];
} *Foo;
如果你愿意,你可以做对,这是另一个原因 不 typedef
一个指针 ,这会起作用
typedef struct
{
int num;
char letter;
void *pointers[2];
} Foo;
Foo *foo_pointer = malloc(N * sizeof(Foo));
/* ^ this would be wrong if `Foo' were a pointer */
if (foo_pointer == NULL)
please_abort_this_do_not_continue_because_malloc_has_failed();
foo_pointer[0].num = 1;
foo_pointer[0].letter = 'a';
1写这个真的很烦我,因为typedef
指针从来都不是一个好主意
如果您想使用结构,您必须分配结构并将其指针保存到 items
的元素。否则,item
的元素是垃圾,访问它可能会导致错误。
由于删除了 malloc
并将 items[0]->num
和 items[0]->letter
的值直接传递给 printf
.[=16= 的优化,第二个测试可能工作正常]
您的初始 malloc:
Foo* items = malloc(sizeof(Foo) * 4);
正在创建一个包含 4 个指针的数组,因为 Foo
是指针类型。所以你的第二个 malloc:
items[0] = malloc(sizeof(*items[0]));
有道理,因为您正在为该指针分配一个结构。
但是,您正在执行的分配会导致未定义的行为,因为您没有执行第二个 malloc
,因此尚未将 space 分配给 items[0]
。 C 不会阻止您写入不应该写入的内存位置。一旦你这样做,任何事情都可能发生。
这里有点令人困惑的一件事是您使用 typedef
来定义指针类型。这可能会导致很多混乱,因为通过查看它是指针的类型并不明显。在这种情况下,由于您定义 Foo
的方式,您可能不需要额外的指针间接层。
因此,如果您这样定义结构:
typedef struct
{
int num;
char letter;
} Foo;
那么这就可以安全地完成了:
Foo* items = malloc(sizeof(Foo) * 2);
items[0].num = 4;
items[0].letter = 'a';
printf("items[0] = {num=%d, char=%c}\n", items[0].num, items[0].letter);
现在 malloc 创建结构数组而不是结构指针数组,因此不再需要额外的 malloc 层。