为什么在整数常量表达式中使用浮点运算是无效的?

Pav*_*kin 1 c floating-point language-lawyer constant-expression c11

在 C11(及更高版本)中,整数常量表达式只能具有以下操作数,特别是:

作为强制转换的直接操作数的浮点常量

下面的代码:

int a[ A > B ? 16 : 32 ];
Run Code Online (Sandbox Code Playgroud)

AB是浮点常量时,在 C 中无效:

$ echo '#include "t576.h"' | clang -std=c11 -pedantic -Wall -Wextra -DA=1.0 -DB=2.0 -c -xc -
In file included from <stdin>:1:
./t576.h:1:5: warning: size of static array must be an integer constant expression [-Wpedantic]
Run Code Online (Sandbox Code Playgroud)

但在 C++ 中有效:

$ echo '#include "t576.h"' | clang++ -std=c++11 -pedantic -Wall -Wextra -DA=1.0 -DB=2.0 -c -xc++ -
<nothing>
Run Code Online (Sandbox Code Playgroud)

此要求的起源/理由是什么?

额外问题:在未来的 C 标准修订中,删除这个要求会有用吗?

Eri*_*hil 5

此要求的起源/理由是什么?

这意味着 C 编译器不需要能够在编译器内执行浮点运算。当针对与编译器主机平台不同的目标平台进行编译时,复制目标浮点运算的确切行为可能需要大量工作。(在广泛采用 IEEE 754 浮点运算标准之前尤其如此。)

要在 C 程序中实现浮点语义,编译器只需能够将源代码中的常量转换为目标浮点格式并获取其中的整数部分(通过强制转换)。它不必能够对它们执行一般算术运算。如果没有这个要求,编译器将不得不重现目标平台的浮点算术运算。因此,如果程序使用浮点运算,编译器只需生成执行运算的指令即可实现;它本身不必进行算术运算。对于可用作初始值设定项的算术常量表达式也是如此:C 标准并不严格要求编译器计算初始值设定项的值。它可以生成在程序开始运行时(用于静态对象的初始化)或在需要时(用于自动对象的初始化)计算值的指令。

相反,整数常量表达式可以用在编译器需要值的地方,例如位域的宽度。因此编译器必须能够自行计算该值。如果需要能够进行浮点运算来获取值,这会给编写一些编译器增加相当大的负担。

额外问题:在未来的 C 标准修订中,删除这个要求会有用吗?

删除它将为 C 程序编写者提供一些使用其他常量表达式的机会,并要求 C 编译器编写者做更多的工作。这些东西的价值是主观的。