【问题标题】:C flexible arrays vs pointersC 灵活数组与指针
【发布时间】:2015-12-13 09:59:20
【问题描述】:
struct ss {
    char foo[];
    char bar[3];
    int bazSize;
    char baz[];
}

在上面,foo 显然是一个 4 或 8 字节长的指针。 bar 是一个数组,长度为 3 个字节。 baz 曾经是一个指针,8 字节长。但在 C99 中,baz 是一个灵活的数组。 (传统上定义为baz[0]。)

规则是什么?编译器如何知道 foo 与 baz 完全不同?这怎么不能破坏任何恰好在结构末尾有指针的代码? [] 现在与 * 不同了吗?

【问题讨论】:

  • 你的代码不是合法的 C,所以这个问题没有实际意义。
  • 该结构在 C 中无效,并且没有编译器允许它。一个未指定长度的数组只能作为结构的最后一个元素。
  • @datenwolf 编译器允许奇怪的事情。我今天看到另一个问题,它接受了int x; struct foo { int y[x]; int z[x]; int q[x]; }
  • @M.M:有没有可能,这是一个在函数中定义的结构,而编译器使用了 C99 标准?在那种情况下,我认为它可能是允许的,但我会先咨询标准以确定。
  • @datenwolf 在 C99 中是不允许的

标签: c


【解决方案1】:

您的结构声明不正确:char foo[]; 只能作为最后一个成员出现,并且在末尾缺少 ;。这是正确的声明:

struct ss {
    char *foo;
    char bar[3];
    int bazSize;
    char baz[];
};

最后我们有一个指针foo 和一个灵活的数组baz。从堆中分配这样的结构时,必须知道最后一个成员的实际空间,并且如果不重新分配其结构,则不能更改如果它从其他地方引用的结构可能会很复杂。灵活的数组节省空间,但根本不是灵活的

灵活数组的优点:

  • 节省空间
  • 保存一个间接方法
  • 一步到位
  • baz 永远不是 NULL

相反,将baz 设为指针需要单独分配它指向的数组。这种在尺寸、代码和速度方面的劣势是有补偿的。

指针版的优点:

  • baz 可以是NULL 以不指定数据。
  • 当实际大小已知时,baz 可以按需分配。
  • baz 可以轻松重新分配。

所以你应该使用哪个取决于你如何使用这些结构。使用时的语法是相同的,但编译器已经看到了实际的声明并将生成适当的代码。

【讨论】:

    【解决方案2】:

    问题在于char *foochar foo[] 在某些情况下(如函数参数声明)和其他情况下(如结构字段声明)不同。

    (我已经很久没有黑过C了。)

    【讨论】:

      【解决方案3】:

      首先,您需要初始化 foo 和 baz 以使代码实际编译。那么编译器就清楚这两者的区别是什么了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多