【发布时间】:2020-10-22 05:17:32
【问题描述】:
考虑这段代码:
#include <stdio.h>
int main(void)
{
/* TEST 1 */
double d = 128;
char ch = (char)d;
printf("%d\n", ch);
/* TEST 2 */
printf("%d\n", (char)128.0);
/* TEST 3 */
char ch1 = (char)128.0;
printf("%d\n", ch1);
return 0;
}
结果:
gcc* clang* cl*
TEST 1 -128 -128 -128
TEST 2 127 0 -128
TEST 3 127 -2 -128
* latest version
问题:
- 为什么不同测试的结果不同(不包括
cl)? - 为什么编译器之间的结果不同(不包括
TEST 1)? - 如果是 UB/IB,UB/IB 到底在哪里?标准是怎么说的?
- [额外问题] 为什么
clang表现出如此不同的行为?这些0和-2来自哪里?
【问题讨论】:
-
有符号整数溢出是未定义行为。
-
就 clang 而言,由于它是 UB,clang 可能已经对此进行了优化,以使包含该参数的寄存器/内存位置为调用前的任何值。
-
有趣的是,gcc 和 clang 都没有对此发出警告,即使是
-Wall -W或-Weverything。似乎编译器“知道”正在调用未定义的行为。 -
似乎是演员消除了警告。
char c = 128.0确实发出警告。也许,就像在其他情况下一样,演员表被视为“我知道我在做什么”的信号。 -
嗯,通常当用户“显式运行到 UB”时,这意味着他们对他们正在使用的编译器实际要做什么有一定的了解,并且他们希望它这样做。