Kir*_*rov 11 c c++ standards cross-platform 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 ) );
Run Code Online (Sandbox Code Playgroud)
换句话说,编译器是否总是处理固定大小的无符号数的不同二进制表示,或者它是特定于平台的?
如果variable
是有符号整数类型(例如int
),它的值是
什么是标准说这个?
PS和,是的,我在这两个很有趣的- 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
Run Code Online (Sandbox Code Playgroud)
5.8 Shift Operators
在C++标准中也说过:
如果右操作数为负数,或者大于或等于提升左操作数的位长度,则行为未定义.
因此,如果将整数移位的位数多于输入的位数,则输入未定义的行为.例如,如果你将一个short
值左移17位,它可能会在某些机器上给你UB,但不是全部.
6.5.7 Bitwise shift operators
除了其他事情,C11说:
结果
E1 >> E2
是E1
右移位E2
位置.如果E1
具有无符号类型或者E1
具有有符号类型和非负值,则结果的值是商的整数部分E1 / 2
E2
.如果E1
具有有符号类型和负值,则结果值是实现定义的.
因此,签名号码转换不可移植.
所以,一般为整数的回答一般 是:
免责声明:我隐含地假设您正在谈论具有固定宽度的整数类型.否则位移非常危险......
标准:n3337 C++ 11
对于无符号类型或有符号类型(*)中的正值,移位的定义是数学的,因此不受底层硬件表示的影响.
5.8移位运算符[expr.shift]
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操作数
˜
应具有整数或无范围的枚举类型; 结果是其操作数的一个补码.5.11按位AND运算符[expr.bit.and]
1执行通常的算术转换; 结果是操作数的按位AND功能.运算符仅适用于整数或无范围的枚举操作数.
5.13按位包含OR运算符[expr.or]
1执行通常的算术转换; 结果是其操作数的按位包含OR函数.运算符仅适用于整数或无范围的枚举操作数.
但是我承认我对后两者不太确定,我找不到任何按位XX函数的定义,所以即使我相信他们指的是数学对应物,我也无法保证.
(*)感谢phresnel指出这一点.
归档时间: |
|
查看次数: |
1305 次 |
最近记录: |