![](/img/trans.png)
[英]warning: conversion to 'unsigned char' from 'int' may alter its value
[英]g++ warning: conversion to uint16_t from int may alter its value
在高-Wconversion
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
,因为用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
,您的选择是:
-Wconversion
但是在它修好之前不要屏住呼吸,有一个关于这个的错误 ,在2009年开放。
一张纸条:
从历史上看,我不想使用比我需要的更多的位,只需让编译器根据需要处理促销/转换/填充。
如果您使用较短的类型进行存储,那很好。 但通常情况下,没有理由使用比int
更短的类型来算术。 它没有加速(即使,它可能会更慢,因为不必要的掩码)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.