gpt4 book ai didi

c - 如果指数是变量,为什么从 pow() 输出的超大值不以相同的方式强制转换?

转载 作者:太空狗 更新时间:2023-10-29 15:34:39 26 4
gpt4 key购买 nike

我在进行一些按位练习时遇到了这个不寻常的错误。当 pow() 的输出被强制为 unsigned int , pow() 的结果当指数变为零时使用变量调用,而当指数为文字整数时,结果被 正常 强制为0xFFFFFFFF(2^32 - 1).只有当值过大(在本例中为 2^32)时才会发生这种情况。用作指数参数的变量类型似乎不会影响此结果。我还尝试将两次调用的输出存储到 pow()作为 double ,然后在引用变量时应用强制转换;差距依然存在。

#import <math.h>

int main (void) {
int thirtytwo = 32; // double, unsigned, etc... all yielded the same result

printf("Raw Doubles Equal: %s\n", pow(2, 32) == pow(2, thirtytwo) ? "true" : "false"); // -> true
printf("Coerced to Unsigned Equal: %s\n", (unsigned) pow(2, 32) == (unsigned) pow(2, thirtytwo) ? "true": "false"); // -> false

return 0;
}

出于好奇,我通过 clang/llvm 运行相同的代码,并获得了不同的结果:无论指数是否为变量,将结果强制转换为 unsigned int 会产生零(如预期)。

编辑:最大 32 位无符号整数是 2^32 - 1 ,因此强制输出实际上正确。我的错误是超出了整数大小限制。为什么 gcc 基本上四舍五入到最大整数值是一个有趣的好奇心,但不是特别重要。

最佳答案

编译器将使用常量折叠将 pow(2, 32) 替换为常量结果; pow(2, thirttwo) 将在运行时计算。 C11 实际上允许编译时计算比相应的运行时计算(C11 6.6p5)精确:

If a floating expression is evaluated in the translation environment, the arithmetic range and precision shall be at least as great as if the expression were being evaluated in the execution environment.

例如,众所周知,GCC 就是这样做的。因此,C 标准并不真正要求第一个打印 true (and in practice this does occur in some implementations)。


至于为什么第二个打印false:是因为pow(2 ^ 32)不能用32位的unsigned int表示。 C11 6.3.1.4 :

When a finite value of real floating type is converted to an integer type other than _Bool, the fractional part is discarded (i.e., the value is truncated toward zero). If the value of the integral part cannot be represented by the integer type, the behavior is undefined.

因此,第二个输出 false 是由于未定义的行为。与将整数转换缩小为无符号整数不同,对于从 float 到偶数无符号整数的转换,溢出是明确未定义的。

值得注意的是,我无法让我的 GCC 6.2.0 警告 (unsigned int)pow(2, 32) 的编译时未定义行为。 (我尝试使用 -lm -Wall -Werror -pedantic -ubsan -Wfloat-conversion -Wconversion -Wextra -std=c11 没有任何输出)。

关于c - 如果指数是变量,为什么从 pow() 输出的超大值不以相同的方式强制转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43062561/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com