灵活数组成员的非静态初始化? #包括 #包括 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
指向
的指针数量

要初始化
的每个成员,必须将有效的地址分配给
类型的结构(或者可以单独分配、复制到新块,然后将该块的起始地址分配给
中的指针)在您的情况下,您有一个名为
水果
的结构
数组。要分配给
,必须将每个结构的地址分配给
项中的每个元素
(请记住,您有指针的存储空间,而不是struct
item的存储空间
——并且您必须确保
水果
在您使用
篮子
期间保持在范围内)

将这些部分放在一起,您可以执行以下类似操作:

typedef struct item_coll {
    size_t length; Item *items;
} ItemColl;
内存使用/错误检查

在您编写的任何动态分配内存的代码中,对于所分配的任何内存块,您有两个责任:(1)始终保留指向内存块起始地址的指针,以便(2)在不再需要它时可以释放它

必须使用内存错误检查程序,以确保您不会试图访问内存或写入超出/超出分配的块的边界,尝试在未初始化的值上读取或建立条件跳转,最后确认释放所有已分配的内存

对于Linux
valgrind
是正常的选择。每个平台都有类似的内存检查器。它们都很容易使用,只需运行程序即可

$ ./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)