解释整数与提升的比较 我试图理解C++中的整数提升和比较是如何工作的。p> #include <cstdint> int main(void) { uint32_t foo = 20; uint8_t a = 2; uint8_t b = 1; uint8_t c = 5; if(foo == b*c) {} if(foo == a) {} if(foo == a + c) {} if(foo == a + b*c) {} return 0; } #包括 内部主(空) { uint32_t foo=20; uint8_t a=2; uint8_t b=1; uint8_t c=5; 如果(foo==b*c){} 如果(foo==a){} 如果(foo==a+c){} 如果(foo==a+b*c){} 返回0; }
仅在最后一次比较中,我收到一条编译器警告:“有符号和无符号整数表达式之间的比较[-Wsign compare]”解释整数与提升的比较 我试图理解C++中的整数提升和比较是如何工作的。p> #include <cstdint> int main(void) { uint32_t foo = 20; uint8_t a = 2; uint8_t b = 1; uint8_t c = 5; if(foo == b*c) {} if(foo == a) {} if(foo == a + c) {} if(foo == a + b*c) {} return 0; } #包括 内部主(空) { uint32_t foo=20; uint8_t a=2; uint8_t b=1; uint8_t c=5; 如果(foo==b*c){} 如果(foo==a){} 如果(foo==a+c){} 如果(foo==a+b*c){} 返回0; },c++,integer-promotion,C++,Integer Promotion,仅在最后一次比较中,我收到一条编译器警告:“有符号和无符号整数表达式之间的比较[-Wsign compare]” 为什么这只发生在最后一种情况下,而不发生在其他情况下?由于操作数的类型不同,因此会进行一组隐式转换以达到一个公共类型 对于二进制运算符(移位除外),如果提升的操作数 如果具有不同的类型,则需要额外的隐式转换集 应用,如往常所知,目标是 生成公共类型(也可通过std::common_类型访问 (特征) 由于这里的积分类型,积分转换应用于: 如果任一操作数具有作用域枚举类型,则不执行任
为什么这只发生在最后一种情况下,而不发生在其他情况下?由于操作数的类型不同,因此会进行一组隐式转换以达到一个公共类型 对于二进制运算符(移位除外),如果提升的操作数 如果具有不同的类型,则需要额外的隐式转换集 应用,如往常所知,目标是 生成公共类型(也可通过std::common_类型访问 (特征) 由于这里的积分类型,积分转换应用于:
- 如果任一操作数具有作用域枚举类型,则不执行任何转换:另一个操作数和返回类型必须具有相同的值
类型- 否则,如果任一操作数为长双精度,则另一个操作数将转换为长双精度
- 否则,如果任一操作数为双精度,则另一个操作数将转换为双精度
- 否则,如果任一操作数为浮点,则另一个操作数将转换为浮点
- 否则,操作数为整数类型(因为bool、char、char8、char16、char32、wchar和unscope枚举 此时已升级)和积分转换 应用生成通用类型,如下所示:
- 如果两个操作数都有符号或都无符号,则转换秩较小的操作数将转换为具有 更大的整数转换秩
- 否则,如果无符号操作数的转换秩大于或等于有符号操作数的转换秩
操作数,有符号操作数转换为无符号操作数
操作数的类型 - 否则,如果有符号操作数的类型可以表示无符号操作数的所有值,则无符号操作数将转换为 有符号操作数的类型否则,两个操作数都将转换为 有符号操作数类型的无符号对应项
rhs
都是uint8\u t
,公共类型将是int,然后因为rhs
是uint32\u t
,=
运算符的公共类型将是uint32\u t
。
但是由于某种原因,我不知道在clang执行最后一次转换时,gcc不执行最后一次转换。请参阅中的+
运算符的gcc
类型转换
该警告也可能是错误警告,并且发生了转换,就像对+
运算符发生的那样。
查看clang
如何查看最后一个if
():
if(foo==static_cast(静态_cast(a)+(静态_cast
(b) *静态(c)))
更新:
我在两个编译器生成的程序集中找不到差异,我同意@M.M,因此,我认为这是一个gcc
错误。这是一个编译器“错误”。要详细说明这一点:
- 通常,有符号和无符号之间的比较依赖于实现定义的数量(类型的大小/范围)。例如,
在普通16位系统上为真,在普通32位系统上为假。“遗忘”一词的答案涉及到更多的技术细节USHRT\u MAX==-1
- 您的所有代码示例都定义良好,在所有(一致性)系统上的行为都相同
GCC倾向于在警告方面犯太多的错误,但他们的处境是无法取悦所有人。
b*c
,a+c
和a+b*c
都被提升为int
s。由于某些原因,您的编译器仅对其中一个发出警告。哪个编译器、哪个版本以及哪个命令行开关?@EricPostpischil,这在g++6.3.0中可以通过-Wall
重现。在g++7.4.0中,“不执行转换”和“不警告执行转换”之间也有区别。这个问题只是提供了缺乏警告的证据,而不是没有进行转换。为了提供编译器没有实际执行所需转换的证据,有必要检查输出代码(汇编程序等)。@Peter您是对的,必须检查汇编程序。也许这个警告是错误的。我编辑我的声明这不是一个大惊喜,未签名的被提升为签名的?如果没有C++律师学位,我会想说这是根本问题。
if(foo == static_cast<unsigned int>(static_cast<int>(a) + (static_cast<int>
(b) * static_cast<int>(c))))