我收到警告"浮点溢出"

时间:2014-11-26 03:10:50

标签: c floating-point type-conversion

#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;来了?

编译器显示:

  

警告:浮点溢出

1 个答案:

答案 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

  

否则,如果具有无符号整数类型的操作数具有等级   那么,大于或等于另一个操作数的类型的等级   带有符号整数类型的操作数转换为   具有无符号整数类型的操作数。