【问题标题】:C99 VLA size determination and sizeof operatorC99 VLA 大小确定和 sizeof 算子
【发布时间】:2015-03-18 09:54:07
【问题描述】:

作为对question 关于sizeof 及其在C99 VLA 方面的行为的回答的一部分,我写了以下内容:

故意创建一个案例,其中count_of 的语义对于 VLA 来说实际上会有所不同,但可能很难创建一个可读、易于理解/可维护且有用的案例案例(我没试过)。

想了想,我不确定这句话是否属实。要首先创建 VLA,编译器必须首先确定 VLA 需要的空间量。

对于sizeof,我们知道

如果操作数的类型是变长数组类型,则计算操作数;否则,不计算操作数,结果是一个整数常量。 (6.5.3.4/2)

虽然 VLA 大小显然是运行时确定的,但在对 VLA 声明符的大小表达式进行评估(如果有的话,包括任何副作用)之后:

可变长度数组类型的每个实例的大小在其生命周期内不会改变。如果 size 表达式是 sizeof 运算符的操作数的一部分,并且更改 size 表达式的值不会影响运算符的结果,则未指定是否计算 size 表达式。 (6.7.5.2/2)

所以,给定

#define count_of(arr)  (sizeof(arr)/sizeof(arr[0]))

是否存在任何这样的宏的实际有效行为对于 VLA 与数组声明是一个常量表达式(即普通的旧的 C99 之前的固定大小数组)?

【问题讨论】:

    标签: c language-lawyer


    【解决方案1】:

    显而易见的答案是arr 是一个包含副作用的表达式。如果评估sizeof 的参数,则会产生副作用。如果不进行评估,则没有副作用。

    #include <stdio.h>
    #define LENGTHOF(arr) (sizeof(arr) / sizeof(*(arr)))
    void f() {
      puts("f");
    }
    int main() {
      const int n = 4;
      int array[n];
      return LENGTHOF(*(f(), &array)) - 4;
    }
    

    这在 C99 中有效,其中 array 是 VLA,在 C++ 中有效,其中 n 是常量表达式,array 不是 VLA。在 C99 中,这将打印 f。在 C++ 中,这不会打印任何内容。

    【讨论】:

    • 哎哟。逗号运算符再次罢工......编辑:为什么array上的地址?编辑:明白了。
    • 如果您不喜欢逗号运算符,您可以使用int array[n][n];int i = 0;LENGTHOF(array[i=1]) 以获得类似的效果。
    • 但如果我使用gcc -std=c90 -Wall 编译,则会打印出fgcc 错了吗? (debian 上的 gcc v4.7.2)
    • @frasnian 在 C90 中,此程序无效,但允许 GCC 在 C90 模式下接受 VLA 作为扩展。如果您将-pedantic 添加到命令行选项,您应该会收到一条消息。
    • @hvd:明白了,谢谢。我假设(总是一个坏主意)gcc 文档中关于在使用-std=c90 时禁用“某些 GNU 扩展......被禁用”的部分将涵盖 VLA。此外,一旦我的思维过程停留在 VLA 的实施方式和对 VLA 的评估后果上,我开始完全跳过关于sizeof 的评估位,尽管我最初的原因是在我的回答中考虑它链接的问题 - 甚至在这里再次引用它 - 哦! (拍自己的额头)。
    猜你喜欢
    • 2015-12-18
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    • 2016-06-25
    • 2017-02-11
    • 2011-02-09
    • 2016-07-23
    相关资源
    最近更新 更多