位操作的标准(跨平台)方法
Standard (cross-platform) way for bit manipulation
是数字的不同二进制表示形式(例如,取大/小端序),这是跨平台的:
// NOTE: FIXED-SIZE unsigned integral type
some_unsigned_type variable = some_number;
// set n-th bit, starting from 1,
// right-to-left (least significant-to most significant)
variable |= ( 1 << ( n - 1 ) );
// clear the same bit:
variable &= ~( 1 << ( n - 1 ) );
换句话说,编译器是否始终负责固定大小的无符号数字的不同二进制表示形式,或者它是特定于平台的?
如果variable
是有符号整型(例如,int
)并且其值为
- 零
- 阳性
- 阴性?
《标准》对此有何规定?
附言而且,是的,我对两者都很有趣 -C
和C++
,请不要告诉我它们是不同的语言,因为我知道这个:)
如果需要,我可以粘贴真实示例,但帖子会变得太长
除非some_unsigned_type
是固定宽度的类型,否则这是您的第一个特定于平台的类型。在一个平台上,您可能会转移一些值本身永远不会重复的信息,而在另一个平台上,它可能不会。例:
16 bit 'int':
1000 0000 0000 0000
<<1 = 0000 0000 0000 0000
>>1 = 0000 0000 0000 0000
32 bit 'int':
0000 0000 0000 0000 1000 0000 0000 0000
<<1 = 0000 0000 0000 0001 0000 0000 0000 0000
>>1 = 0000 0000 0000 0000 1000 0000 0000 0000
C++标准中的5.8 Shift Operators
也这样说:
行为未定义,如果正确的操作数 为负数,或大于或等于提升的左操作数的长度(以位为单位)。
因此,如果将整数移动的位数多于实际位数,则会进入未定义的行为。 例如,如果将short
值左移 17 位,它可能会在某些机器上为您提供 UB,但不是全部。
C11在6.5.7 Bitwise shift operators
中说,除了其他事情之外,这个:
E1 >> E2
的结果是E1
位位置右移E2
。如果E1
具有无符号类型 或者,如果E1
具有有符号类型和非负值,则结果的值为整数E1 / 2
E2
商的一部分。如果E1
具有有符号类型和负值,则 结果值由实现定义。
因此,符号数字移位是不便携的。
因此,整数的一般答案是:
对整数的按位操作不可移植。
免责声明:我隐含地假设您正在谈论具有固定宽度的整数类型。否则移位是非常危险的...
标准: n3337 C++11
移位的定义对于无符号类型或有符号类型 (*) 中的正值是数学定义的,因此不受基础硬件表示形式的影响。
5.8 移位运算符
2
E1 << E2
的值E1
E2
位位置左移;空出的位填充为零。如果E1
具有无符号类型,则结果的值为E1 × 2
E2
,比结果类型中可表示的最大值多减模 1。否则,如果E1
具有有符号类型和非负值,并且E1×2
E2
在结果类型中可表示,则这就是结果值;否则,行为是未定义的。3
E1 >> E2
的值E1
E2
位位置右移。如果E1
具有无符号类型,或者E1
具有有符号类型和非负值,则结果的值是E1/2
E2
商的整数部分。如果E1
具有带符号类型和负值,则结果值由实现定义。
出于同样的原因,我认为按位and
、or
和negate
是可以的:它们是用数学定义的。
5.3.1 一元运算符 [expr.unary.op]
10
˜
的操作数应具有整备或无作用域枚举类型;结果是其操作数的 one 补码。5.11 按位 AND 运算符 [expr.bit.and]
1执行通常的算术转换;结果是操作数的按位 AND 函数。运算符仅适用于整型或无作用域枚举操作数。
5.13 按位包含 OR 运算符 [expr.or]
1执行通常的算术转换;结果是其操作数的按位包含 OR 函数。运算符仅适用于整型或无作用域枚举操作数。
然而,我承认我对后两者不太确定,我找不到按位XX函数的任何定义,所以即使我相信他们指的是数学对应物,我也不能保证。
(*) 感谢 phresnel 指出这一点。
如果您移动负数(或有符号)数字(通过大多数实现是相同的 U2 事物),它是特定于实现的。如果您将无符号数字移位的值不超过变量中的位数,则大多数用途都是可移植的。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 是否有跨平台的方法可以在C++中禁用已弃用的警告?
- 是否有一种跨平台的方法可以在使用 C++ 编写的二进制应用程序中嵌入资源?
- 在转换为较小的数值类型之前执行范围检查的安全、跨平台方法是什么
- 如何在Mac OS X上使用Qt设置libusb?(尝试跨平台方法)
- 有没有一种很好的跨平台方法可以使用CMake包含外部C++库
- 是否有跨平台方法列出可用的串行端口
- 位操作的标准(跨平台)方法
- 跨平台最佳 MVC 模型到控制器消息传递方法(C#、Objective-C++)
- 使用 Python 插件可扩展性编写跨平台应用程序的最简单方法
- 通过服务器在互联网上传输加密视频的跨平台方法
- 从函数指针创建boost::函数的跨平台方法
- 解析文本文件最好的、跨平台的方法是什么?
- 在C++中执行跨平台线程间通知的好方法是什么?
- 如何使用跨平台方法确定驱动器类型
- 跨平台访问配置目录的方法
- 跨平台发送大量数据的好方法是什么?
- 设计跨平台多内容类型文件格式的最佳方法
- 是否有一种跨平台的方法可以在C++中获取网络统计信息
- 跨平台-从c++运行GLSL着色器(尚未编译)的最简单方法是什么?