#include<stdio.h>
main()
{
short int b = (short int)(((-100) * (1UL << 6)) - 0.5);
short int c = (short int)( (-6400) - 0.5 );
printf("%d",sizeof(short int));
printf("\n%d",b);
printf("\n%d",c);
}
输出:
b:32767
c:-6400
为什么我会得到不同的结果? 这是因为类型转换?
由于我无法在此处输入完整的代码副本,因此我编写了在键盘中显示警告并将其粘贴到此处的部分。 我正在使用Posek编译器。 以上表达式用于其中一个配置中。当我在Trace32中运行代码时,我发现它已经获得了值#34; -1&#34;。我没有得到价值&#34; -1&#34;来了?
编译器显示:
警告:浮点溢出
答案 0 :(得分:0)
您的问题在这里:
(-100) * (1UL << 6)
^^^
乘法对其操作数执行通常的算术转换,然后针对此情况执行整数提升,并导致-100
转换为无符号长整数,这意味着它将具有非常大的无符号值,不适合签名短。这是烧尽整数溢出,这是未定义的行为。
修复方法如下:
(-100) * (1 << 6)
^^
请注意,sizeof
不会返回 int printf
的正确格式说明符%zu
。
使用clang
和以下标志-std=c99 -Wall -Wextra -Wconversion -pedantic
打开编译器上的警告确实有帮助我收到了以下警告:
warning: implicit conversion changes signedness: 'int' to 'unsigned long' [-Wsign-conversion]
short int b = (short int)(((-100) * (1UL << 6)) - 0.5);
^~~~ ~
warning: format specifies type 'int' but the argument has type 'unsigned long' [-Wformat]
printf("%d",sizeof(short int));
~~ ^~~~~~~~~~~~~~~~~
%lu
供参考,草案C99标准部分6.5.5
乘法运算符表示:
通常的算术转换是在操作数上执行的。
和部分6.3.1.8
通常的算术转换表示:
否则,将对两个操作数执行整数提升。然后 以下规则适用于提升的操作数:
为此,以下情况适用,因为-100
将 int 而另一个操作数 unsigned long :
否则,如果具有无符号整数类型的操作数具有等级 那么,大于或等于另一个操作数的类型的等级 带有符号整数类型的操作数转换为 具有无符号整数类型的操作数。