灵活数组成员的非静态初始化? #包括 #包括 typedef结构项{ int-low;int-high;字符标签[16]; }项目; 类型定义结构项\u coll{ 尺寸/长度;项目*项目[]; }ItemColl; 字符*查找范围内的第一个字符(ItemColl*ic、int rlow、int rhigh){ 对于(大小i=0;ilength;i++) 如果(ic->items[i]->low>=rlow&&ic->items[i]->high items[i]->标签[0]; 返回NULL; } int main(){ 结构项目结果[]={ {10,20,“苹果”}, {12,14,“梨”}, {8,12,“香蕉”}, {2,4,“葡萄”}, {15,35,“西瓜”} }; 结构项_coll basket={5,fruits}; printf(“%s”,在_范围内首先查找_(&basket,21,22)); 返回0; }
这给了我灵活数组成员的非静态初始化? #包括 #包括 typedef结构项{ int-low;int-high;字符标签[16]; }项目; 类型定义结构项\u coll{ 尺寸/长度;项目*项目[]; }ItemColl; 字符*查找范围内的第一个字符(ItemColl*ic、int rlow、int rhigh){ 对于(大小i=0;ilength;i++) 如果(ic->items[i]->low>=rlow&&ic->items[i]->high items[i]->标签[0]; 返回NULL; } int main(){ 结构项目结果[]={ {10,20,“苹果”}, {12,14,“梨”}, {8,12,“香蕉”}, {2,4,“葡萄”}, {15,35,“西瓜”} }; 结构项_coll basket={5,fruits}; printf(“%s”,在_范围内首先查找_(&basket,21,22)); 返回0; },c,C,这给了我app.c:28:32:错误:灵活数组成员的非静态初始化 struct item_coll basket={5,fruits}; 错误指向水果 这是什么意思?我觉得很好。我强烈怀疑你有意这样定义: #include <stdio.h> #include <limits.h> typedef struct item { int low; int high; char label[16]; } Item; typedef struct item_coll
app.c:28:32:错误:灵活数组成员的非静态初始化
struct item_coll basket={5,fruits};
错误指向水果
这是什么意思?我觉得很好。我强烈怀疑你有意这样定义:
#include <stdio.h>
#include <limits.h>
typedef struct item {
int low; int high; char label[16];
} Item;
typedef struct item_coll {
size_t length; Item *items[];
} ItemColl;
char *find_first_in_range(ItemColl *ic, int rlow, int rhigh) {
for (size_t i = 0; i < ic->length; i++)
if (ic->items[i]->low >= rlow && ic->items[i]->high <= rhigh)
return &ic->items[i]->label[0];
return NULL;
}
int main() {
struct item fruits[] = {
{10, 20, "Apple"},
{12, 14, "Pear"},
{8, 12, "Banana"},
{2, 4, "Grape"},
{15, 35, "Watermelon"}
};
struct item_coll basket = {5, fruits};
printf("%s", find_first_in_range(&basket, 21, 22));
return 0;
}
i、 e.长度和项目数组,而不是指向项目的指针数组
如前所述,指针数组没有任何指定的长度,这使得结构实际上不完整;编译器无法告诉hiw它是大的,因此您永远无法实际定义一个。C11允许这种声明是为了方便。未指定长度的数组--“灵活数组成员”--必须位于struct
的末尾,并且struct
本身不能在另一个struct
中使用
您可以使用具有灵活数组成员的结构作为具体动态分配对象的基础,该对象的大小可以计算为sizeof(struct)+n*sizeof(ArrayElement)
。作为一种优化,这偶尔是有用的,而且是合法的;我要说的是,它的明显优势需要与它所造成的代码复杂度进行权衡。我强烈怀疑您有意这样定义:
#include <stdio.h>
#include <limits.h>
typedef struct item {
int low; int high; char label[16];
} Item;
typedef struct item_coll {
size_t length; Item *items[];
} ItemColl;
char *find_first_in_range(ItemColl *ic, int rlow, int rhigh) {
for (size_t i = 0; i < ic->length; i++)
if (ic->items[i]->low >= rlow && ic->items[i]->high <= rhigh)
return &ic->items[i]->label[0];
return NULL;
}
int main() {
struct item fruits[] = {
{10, 20, "Apple"},
{12, 14, "Pear"},
{8, 12, "Banana"},
{2, 4, "Grape"},
{15, 35, "Watermelon"}
};
struct item_coll basket = {5, fruits};
printf("%s", find_first_in_range(&basket, 21, 22));
return 0;
}
i、 e.长度和项目数组,而不是指向项目的指针数组
如前所述,指针数组没有任何指定的长度,这使得结构实际上不完整;编译器无法告诉hiw它是大的,因此您永远无法实际定义一个。C11允许这种声明是为了方便。未指定长度的数组--“灵活数组成员”--必须位于struct
的末尾,并且struct
本身不能在另一个struct
中使用
您可以使用具有灵活数组成员的结构作为具体动态分配对象的基础,该对象的大小可以计算为sizeof(struct)+n*sizeof(ArrayElement)
。作为一种优化,这偶尔是有用的,而且是合法的;我要说的是,它的明显优势需要与它所造成的代码复杂度进行权衡。如果这是一项考试,您必须使用灵活的数组成员,那么正如我在评论中指出的以及@rici在其回答中解释的,FAM的目的是提供一个给定类型的占位符
,该占位符允许您在一次分配中为结构本身分配存储以及为某些FAM类型分配存储。这样做的好处是为结构分配一次分配/一次免费,而不是单独分配,然后再分配一些所需的数据类型
(在FAM之前,有一种被称为struct hack的方法,它使用一个大小为1
的数组来代替它,用于几乎相同的目的)
类型
对于您如何处理和分配FAM至关重要。在您的情况下,您的FAM是项*项[];
(在代码中键入项
--项
)的指针数组),因此您为结构分配,然后分配X
指向项
的指针数量
要初始化项
的每个成员,必须将有效的地址分配给项
类型的结构(或者可以单独分配、复制到新块,然后将该块的起始地址分配给项
中的指针)在您的情况下,您有一个名为水果的结构项数组。要分配给项
,必须将每个结构的地址分配给项中的每个元素
(请记住,您有指针的存储空间,而不是structitem的存储空间
——并且您必须确保水果
在您使用篮子
期间保持在范围内)
将这些部分放在一起,您可以执行以下类似操作:
typedef struct item_coll {
size_t length; Item *items;
} ItemColl;
内存使用/错误检查
在您编写的任何动态分配内存的代码中,对于所分配的任何内存块,您有两个责任:(1)始终保留指向内存块起始地址的指针,以便(2)在不再需要它时可以释放它
必须使用内存错误检查程序,以确保您不会试图访问内存或写入超出/超出分配的块的边界,尝试在未初始化的值上读取或建立条件跳转,最后确认释放所有已分配的内存
对于Linuxvalgrind
是正常的选择。每个平台都有类似的内存检查器。它们都很容易使用,只需运行程序即可
$ ./bin/fam_initialization
Pear
始终确认已释放所有已分配的内存,并且没有内存错误
仔细检查一下,如果您还有其他问题,请告诉我。如果这是一项考试,并且您必须使用灵活的数组成员,那么正如我在评论中指出的以及@rici在其回答中解释的那样,FAM的目的是提供一个给定类型的占位符,然后允许您分配
$ valgrind ./bin/fam_initialization
==6887== Memcheck, a memory error detector
==6887== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==6887== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==6887== Command: ./bin/fam_initialization
==6887==
Pear
==6887==
==6887== HEAP SUMMARY:
==6887== in use at exit: 0 bytes in 0 blocks
==6887== total heap usage: 1 allocs, 1 frees, 48 bytes allocated
==6887==
==6887== All heap blocks were freed -- no leaks are possible
==6887==
==6887== For counts of detected and suppressed errors, rerun with: -v
==6887== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)