【问题标题】:Structure of a book in CC语言一本书的结构
【发布时间】:2021-12-05 06:20:51
【问题描述】:

我是 C 编程新手,在开发本练习时遇到了无法解决的错误:

字段必须具有恒定大小:永远不会支持“结构中的可变长度数组”扩展

#include <stdio.h>
#include <stdlib.h>

int main(int argc, const char * argv[]) {
    int nChapters = 2;
    
    typedef struct {
        char title[50];
        char author[50];
    } Heading;
    
    typedef struct {
        char title[50];
        int number_pages;
    } Chapter;
    
    typedef struct {
        Heading heading;
        Chapter chapters[nChapters]; //Fields must have a constant size: 'variable length array in structure' extension will never be supported
    } Book;
    
    printf("\n");
    system("read -p 'Press enter to continue...' ");
    printf("Hello, World!\n");
    return 0;
}

如果我用 chapters[2] 之类的 int 替换 chapters[nChapters],程序运行没有问题。提前致谢!

【问题讨论】:

  • 错误信息确实说明了一切。 nChapters 是一个变量,而不是编译时常量。结构中的数组只能使用编译时常量,例如实际的文字整数2。这是在 C 中使用宏的少数几个原因之一。就像在 #define NCHAPTERS 2
  • 你应该将Chapter chapters声明为指针,然后动态分配内存
  • 为什么它可以在其中一个在线编译器中工作? onlinegdb.com,我正在使用 Xcode
  • 还要确保你没有编译为 C++。在 C++ 中,const int 被认为是一个整数常量表达式,但在 C 中不是。总体而言,C++ 在各种常量表达式和变量初始化形式方面更加灵活。

标签: c


【解决方案1】:

在 C 中,您必须使用固定长度声明数组,您的 nChapters 变量确实是一个变量。只需添加 const 关键字,即可将其转换为 常量 变量:

const int nChapters = 2

【讨论】:

  • 为什么它可以在其中一个在线编译器中工作? onlinegdb.com,我正在使用 Xcode
  • 我赞成你的回答,但我认为应该指出你的第一句话不一定是真的。有variable-length arrays 的概念,虽然没有得到普遍支持。
  • 使用const 定义变量不会使其成为C 中用于数组声明的常量。 (它可能在 C++ 中。)
【解决方案2】:

你可以使用预处理指令#define:

#define nChapters 2

【讨论】:

  • 为什么它可以在其中一个在线编译器中工作? onlinegdb.com,我正在使用 Xcode
【解决方案3】:

问题是你假设它是显而易见的

Chapter chapters[nChapters];

nChapters 的值是2。 它适用于不在structunion 内的数组。 这是由奇怪的、非标准的、非 GCC 支持的(但在 C90 以后被 GCC 接受为扩展),不推荐的功能称为 VLA 或可变长度数组。使用这些,可以分配一个auto 类数组。

参考GNU/GCC documentation, section 6.20,需要注意的是,

存储在声明时分配,并在包含声明的块范围退出时释放。

C99 推荐了一种更好的方法来处理这个要求 - 使用灵活长度的数组。

§6.7.2.1 结构和联合说明符 ¶18 作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型;这称为灵活数组成员。在大多数情况下,灵活数组成员被忽略。特别是,结构的大小就像省略了柔性数组成员一样,只是它可能具有比省略所暗示的更多的尾随填充。然而,当一个 . (或 -> )运算符的左操作数是(指向)具有灵活数组成员的结构,右操作数命名该成员,它的行为就像该成员被替换为最长的数组(具有相同的元素类型) 不会使结构大于被访问的对象;数组的偏移量应保持灵活数组成员的偏移量,即使这与替换数组的偏移量不同。如果这个数组没有元素,它的行为就好像它只有一个元素,但如果尝试访问该元素或生成一个越过它的指针,则行为是不确定的。

因此,这会将您的结构更改为:

typedef struct {
    Heading heading;
    Chapter chapters[]; 
} Book;

然后从堆中动态分配内存 - 使用malloc

【讨论】:

  • 鉴于这是一个初学者,动态内存和灵活的数组成员现在可能超出了他们的范围。
  • 我在使用 malloc 方面仍然不成熟,但您的回答非常彻底。谢谢!
  • @LAlchimista:不用担心。有很多与 malloc 相关的问题以及在 C 中将它与结构一起使用。从 malloc 开始的最佳点是 -- man7.org/linux/man-pages/man3/realloc.3.html
  • 变长数组不是非标准的(C标准规定了它们),不是非GCC(GCC支持它们),不推荐,也不奇怪。
【解决方案4】:

结构的数组成员的大小必须是常量表达式(跳过“灵活成员”的情况和 GCC 的 VLA-in-struct extension)。

在 C 标准中,拥有真正命名的整数常量的唯一可移植方式是使用枚举。 只需替换:

int nChapters = 2;

用这个:

enum { nChapters = 2 };

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-19
    • 1970-01-01
    • 2018-06-19
    • 2019-05-02
    • 1970-01-01
    相关资源
    最近更新 更多