我刚刚检查了C ++标准。似乎以下代码不应为未定义行为:
unsigned int val = 0x0FFFFFFF;
unsigned int res = val >> 34; // res should be 0 by C++ standard,
// but GCC gives warning and res is 67108863
从标准来看:
E1 >> E2的值是E1右移E2位的位置。如果E1具有无符号类型,或者E1具有带符号类型且非负值,则结果的值是E1 / 2 ^ E2商的整数部分。如果E1具有带符号的类型和负值,则结果值由实现定义。
根据标准,由于34不是负数,因此变量res
将为0。
GCC针对代码段发出以下警告,并且res
为67108863
:
警告:右移计数> =类型的宽度
我还检查了GCC发出的汇编代码。它只是调用SHRL
,而英特尔指令文档中的SHRLres
则不是零。
那么,这是否意味着GCC无法在Intel平台上实现标准行为?
该草案C ++标准在部分5.8
移位运算符在第1说(重点矿山):
结果的类型是提升后的左操作数的类型。如果右操作数为负或大于或等于提升后的左操作数的位长度,则该行为是不确定的。
因此,如果unsigned int类型是32 bits
以下那么这是未定义而这正是该警告gcc
是给你的。
@Zaibis:是的,GCC能够编译C ++。常见的误解是,GCC是(仅)C编译器,或者G ++是不同的编译器。
@Zaibis:GCC是一个工具链;它具有针对C和C ++的编译器(以及链接器和许多其他工具)。