c++中的Sign Extension是编译器选项,还是编译器相关的还是目标相关的?
Is Sign Extension in C++ a compiler option, or compiler dependent or target dependent?
以下代码已在3个不同的编译器和3个不同的处理器上编译,并给出了2个不同的结果:
typedef unsigned long int u32;
typedef signed long long s64;
int main ()
{ u32 Operand1,Operand2;
s64 Result;
Operand1=95;
Operand2=100;
Result= (s64)(Operand1-Operand2);}
Result产生2个结果:要么-5
或4294967291
我确实理解(Operand1-Operand2)
的操作是作为32位无符号计算完成的,然后当转换为s64
符号扩展时,在第一种情况下正确完成,但在第二种情况下没有正确完成。
我的问题是符号扩展是否可以通过编译器选项来控制,或者它是编译器依赖的,或者它可能是目标依赖的。
您的问题是您假设unsigned long int
为32位宽,signed long long
为64位宽。这个假设是错误的
我们可以通过使用具有保证(标准)位宽度的类型来可视化发生的事情:
int main() {
{
uint32_t large = 100, small = 95;
int64_t result = (small - large);
std::cout << "32 and 64 bits: " << result << std::endl;
} // 4294967291
{
uint32_t large = 100, small = 95;
int32_t result = (small - large);
std::cout << "32 and 32 bits: " << result << std::endl;
} // -5
{
uint64_t large = 100, small = 95;
int64_t result = (small - large);
std::cout << "64 and 64 bits: " << result << std::endl;
} // -5
return 0;
}
在这三种情况下,表达式small - large
的结果都是unsigned整数类型(根据宽度)的结果。这个结果是用模运算计算的。
在第一种情况下,由于该无符号结果可以存储在更宽的有符号整数中,因此不执行值转换。
在其他情况下,结果不能存储在有符号整数中。因此,执行实现定义的转换,这通常意味着将无符号值的位模式解释为有符号值。因为结果是"大",所以将设置最高位,当将其作为有符号值(在2的补码下)处理时,相当于一个"小"的负值。显示来自Lưu Vĩnh Phúc:
的注释
Operand1-Operand2
是无符号的,因此当转换为s64时,它总是零扩展。[. .]
符号扩展只在第一种情况下进行,因为只有在这种情况下才有扩展转换,并且它确实总是零扩展。
引自标准,强调我的。关于small - large
:
如果目的类型是无符号的,结果值是与源整数相等于的最小无符号整数(对
2^n$
取模,其中n是用来表示无符号类型的位数)。[. .]§4.7/2
关于无符号到有符号的转换:
如果整型转换的目的类型[]是有符号的,如果该值可以用目的类型表示,则该值不变;否则,该值为实现定义的。
§4.7/3
Sign扩展依赖于平台,其中平台是编译器、目标硬件架构和操作系统的组合。
此外,正如Paul R提到的,内置类型(如unsigned long
)的宽度也依赖于平台。使用<cstdint>
中的类型来获得固定宽度的类型。然而,它们只是依赖于平台的定义,因此它们的符号扩展行为仍然依赖于平台。
这是一个很好的几乎重复的问题,关于字体大小。这里有一个关于字体大小关系的表格
类型提升和相应的符号扩展由c++语言指定。
未指定但与平台相关的是所提供的整数类型的范围。char
, short int
, int
, long int
和long long int
都具有相同的范围,只要该范围满足long long int
的c++标准要求,它甚至符合标准。在这样的平台上,不会发生任何扩大或缩小,但是有符号<->无符号转换仍然可以改变值。
- C/C++编译器通常会删除重复的库吗
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- Win32编译器选项和内存分配
- MSVC多行宏编译器错误
- 静态数据成员的问题-修复链接错误会导致编译器错误
- C++,我收到一个无法理解的编译器错误
- 在线编译器中的分段C++没有打印消息
- 在 CMake 中为每个目标设置编译器/链接器标志
- Cmake:如何构建自定义编译器二进制文件,然后将其用于某些目标?
- qmake中添加了编译器选项的附加makefile目标
- complex.h 适用于 Win32 目标以外的其他编译器,例如代码编辑器工作室 (CCS)
- make如何推断最终目标需要什么样的编译器
- 无法推断编译器目标三元组
- 尝试 std::thread 在尝试调用目标函数时引发编译器错误
- 使用opencv框架的目标C项目的最佳编译器标志
- c++中的Sign Extension是编译器选项,还是编译器相关的还是目标相关的?
- 如何使用Visual C++编译器在Windows上构建库时正确设置目标操作系统版本
- 将VS 2013中的目标编译器更改为VS 2012
- 适合Mac OS X目标的交叉编译器