在高级别SO用户的建议下,我最近开始使用-Wconversion我的代码库上的标志进行编译.这产生了很多警告,其中一些是合法的(例如,不必要的添加signed和unsigned类型),但也有一些头部刮擦,如下所示:
#include <cstdint>
int main()
{
  uint16_t a = 4;
  uint16_t b = 5;
  b += a;
  return 0;
}
当我编译时g++ -Wconversion -std=c++11 -O0 myFile.cpp,我得到了
warning: conversion to 'uint16_t {aka short unsigned int}' from 'int' may alter its value [-Wconversion]
    b += a;
      ^
我细读上SO(处理一些类似的问题|和<<运营商),采取一看这里,并已阅读了数字升级和数值转换部分在这里.我的理解是,为了进行数学计算,a并b被提升为int(因为这是第一种可以适应整个uint16_t值范围的类型),执行数学运算,结果被写回...除了数学结果是一个int并写回来uint16_t生成警告.其他问题的共识基本上是抛弃了警告,而我唯一能想出如何做到这一点的方法就是b = (uint16_t)(b + a);(或等价的b = static_cast<uint16_t>(b + a);).
不要让这个问题过于宽泛,但假设我对整数促销的理解是正确的......
int吗?对我来说似乎很奇怪,我必须转换一个与所有操作数相同类型的算术结果(我希望编译器能够识别并抑制警告).从历史上看,我不想使用比我需要的更多的位,只需让编译器根据需要处理促销/转换/填充.-Wconversion经常使用旗帜吗?在我自己使用它几天之后,我开始认为它的最佳用例是打开它,查看它抱怨的内容,修复合法的投诉,然后将其关闭.或许我对"合法投诉"的定义需要重新调整.+=用拼写的演员阵容取代我的所有操作员似乎比任何事情都更令人讨厌.我很想标记这个c,因为c编译的等效代码gcc -Wconversion -std=c11 -O0 myFile.c会产生完全相同的警告.但就像我在g++x86_64 Fedora 23盒子上使用5.3.1版本一样.如果我错过了,请指点我.如果这里唯一的答案/建议是抛弃警告,那么这就是一个骗局.
我想这也算是gcc的一个缺点吧。
由于此代码不会生成任何警告:
int a = ..., b = ...;
a += b;
此代码不应生成任何一个,因为在语义上它们是相同的(将两个相同类型的数字相加,并将结果放入相同类型的变量中):
short a = ..., b = ...;
a += b;
但是 GCC 会生成警告,因为正如您所说,short' 被提升为int' 。但这个short版本并不比int一个版本更危险,因为如果加法溢出,则该行为是针对该short情况实现定义的,并且针对该int情况是未定义的(或者如果使用无符号数字,则可能会发生截断)两种情况)。
Clang 更智能地处理这种情况,并且不会针对这种情况发出警告。我认为这是因为它实际上跟踪结果的可能位宽(或者范围?)。因此,例如,这警告:
int a = ...;
short b = a;
但这不是(但 GCC 对此发出警告):
int a = ...;
short b = a&0xf; // there is a conversion here, but clang knows that only 4 bits are used, so it doesn't warn
所以,直到 GCC 拥有更智能的-Wconversion,您的选择是:
-Wconversion但在修复之前不要屏住呼吸,有一个错误,于 2009 年开放。
一张纸条:
从历史上看,我喜欢使用不超过我需要的位,并且让编译器根据需要处理升级/转换/填充。
如果您使用较短的类型来存储,那就没问题了。但通常,没有理由使用比int算术更短的类型。它不会加速(甚至,由于不必要的掩蔽,它可能会更慢)。
| 归档时间: | 
 | 
| 查看次数: | 2945 次 | 
| 最近记录: |