繁体   English   中英

g ++警告:从int转换为uint16_t可能会改变其值

[英]g++ warning: conversion to uint16_t from int may alter its value

在高-Wconversion SO用户的建议下,我最近开始在我的代码库上使用-Wconversion标志进行编译。 这产生了很多警告,其中一些是合法的(例如,不必要地添加有signedunsigned类型),但也有一些头部刮擦,如下所示:

#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(处理一些类似的问题|<<运算符),采取一看这里 ,并已阅读了数字升级和数值转换部分在这里 我的理解是,为了进行数学运算, ab被提升为int (因为这是第一种可以适应整个uint16_t值范围的类型),执行数学运算,结果被写回...除了结果数学是一个int ,并将其写回uint16_t生成警告。 其他问题的共识基本上就是抛弃了警告,我弄清楚如何做到这一点的唯一方法是b = (uint16_t)(b + a); (或等效的b = static_cast<uint16_t>(b + a); )。

不要让这个问题过于宽泛,但假设我对整数促销的理解是正确的......

  1. 处理这一前进的最佳方法是什么? 我应该避免在比int更窄的类型上执行数学运算吗? 对我来说似乎很奇怪,我必须转换一个与所有操作数相同类型的算术结果(我希望编译器能够识别并抑制警告)。 从历史上看,我不想使用比我需要的更多的位,只需让编译器根据需要处理促销/转换/填充。
  2. 有人经常使用-Wconversion标志吗? 在我自己使用它几天之后,我开始认为它的最佳用例是打开它,查看它抱怨的内容,修复合法的投诉,然后将其关闭。 或许我对“合法投诉”的定义需要重新调整。 用拼写出来的演员代替我所有的+=运算符似乎比任何东西都更令人讨厌。

我很想把它标记为c ,因为用gcc -Wconversion -std=c11 -O0 myFile.c编译的等效c代码会产生完全相同的警告。 但就是这样,我在x86_64 Fedora 23盒子上使用g++版本5.3.1。 如果我错过了,请指点我。 如果这里唯一的答案/建议是抛弃警告,那么这就是一个骗局。

处理这一前进的最佳方法是什么?

-Wno-conversion

或者只是不指明。 不过,这只是一个意见。

根据我的经验,对窄整数运算的需求往往很少,因此您仍然可以为项目保留它,并禁用发生此无用警告的少数情况。 但是,这可能在很大程度上取决于您的项目类型,因此您的体验可能会有所不同。

我应该避免在比int更窄的类型上执行数学运算吗?

通常是; 除非您有特定的理由使用它们。 “我不需要额外的位”在我看来并不是一个特定的理由。 无论如何,算术操作数被提升为int ,并且通常使用int更快且更不容易出错。

在我自己使用它几天之后,我开始认为它的最佳用例是打开它,查看它抱怨的内容,修复合法的投诉,然后将其关闭。

这通常是警告标志的有用方法,这些标志既不包含在-Wall也不包含在-Wextra例如带有-Wsuggest-前缀的-Wsuggest- 他们没有被列入“所有警告”的原因。

我认为这可以被认为是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 ,您的选择是:

  1. 不要使用-Wconversion
  2. 修复它打印的所有警告
  3. 改用clang(也许是GCC:关掉这个警告;对于clang:打开它)

但是在它修好之前不要屏住呼吸,有一个关于这个的错误 ,在2009年开放。

一张纸条:

从历史上看,我不想使用比我需要的更多的位,只需让编译器根据需要处理促销/转换/填充。

如果您使用较短的类型进行存储,那很好。 但通常情况下,没有理由使用比int更短的类型来算术。 它没有加速(即使,它可能会更慢,因为不必要的掩码)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM