【问题标题】:I'm getting warning "floating point overflow "我收到警告“浮点溢出”
【发布时间】:2014-11-26 03:10:50
【问题描述】:
#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 中运行代码时,我知道它获得了值“-1”。我不明白“-1”这个值是怎么来的?

编译器正在显示:

警告:浮点溢出

【问题讨论】:

  • 我的意思是有符号数和无符号数之间的算术转换。
  • 您的标题提到了“浮点溢出”警告。这是编译时警告吗?
  • 我很好奇您使用的是什么编译器,我没有看到使用 gccclang 的类似警告。
  • @KeithThompson 是的,它是一个编译时警告。
  • @ShafikYaghmour 我正在使用posek编译器。及其赋予值“-1”

标签: c floating-point type-conversion


【解决方案1】:

您的问题在这里:

(-100) * (1UL << 6)
          ^^^

乘法对其操作数执行通常的算术转换,然后在这种情况下进行整数提升,这导致-100 被转换为无符号长整数,这意味着它将有一个非常大的无符号值,不适合有符号短整数。这是未定义行为的单整数溢出。

修复方法如下:

(-100) * (1 << 6)
          ^^

请注意,sizeof 不会返回 intprintf 的正确格式说明符应该是 %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

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

【讨论】:

  • 我同意你的看法。我知道它是因为算术转换。我在我的一个配置中使用了上述表达式。我正在使用posek编译器。当我在 Trace32 中运行代码时,配置的值为 -1。所以我不明白“-1”是怎么出现的?
  • @Harsha 我不熟悉posek。当你说上面的表达式时,你的意思是(short int)(((-100) * (1UL &lt;&lt; 6)) - 0.5)吗?也许 Trace32 处理溢出的方式不同。
  • 是的,同样的表达方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
相关资源
最近更新 更多