位操作的标准(跨平台)方式

时间:2020-12-06 12:05:27

As are are different binary representation of the numbers (for example, take big/little endian), is this cross-platform:

由于是数字的不同二进制表示(例如,采取大/小端),这是跨平台:

// 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 ) );

In other words, does the compiler always take care of the different binary representation of the fixed size unsigned numbers, or it's platform-specific?

换句话说,编译器是否总是处理固定大小的无符号数的不同二进制表示,或者它是特定于平台的?

And what if variable is signed integral type (for example, int) and its value is

如果变量是有符号整数类型(例如,int)并且其值是

  • zero
  • positive
  • negative?

What does the Standard say about this?

标准对此有何看法?

P.S. And, yes, I'm interesting in both - C and C++, please don't tell me they are different languages, because I know this :)

附:而且,是的,我对C和C ++都感兴趣,请不要告诉我他们是不同的语言,因为我知道这个:)

I can paste real example, if needed, but the post will become too long

如果需要,我可以粘贴真实的例子,但帖子会变得太长

3 个解决方案

#1


4  

Disclaimer: I am implicitly assuming that you are talking about an integer type with a fixed width. Bit-shifting otherwise is quite hazardous...

免责声明:我隐含地假设您正在谈论具有固定宽度的整数类型。否则,位移非常危险......

Standard: n3337 C++11

标准:n3337 C ++ 11

The definition of shifts is mathematical for unsigned types or positive values in signed types (*), and therefore not affected by the underlying hardware representation.

对于无符号类型或有符号类型(*)中的正值,移位的定义是数学的,因此不受底层硬件表示的影响。

5.8 Shift operators [expr.shift]

5.8移位运算符[expr.shift]

2 The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are zero-filled. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. Otherwise, if E1 has a signed type and non-negative value, and E1×2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

2 E1 << E2的值是E1左移E2位的位置;空位是零填充的。如果E1具有无符号类型,则结果的值为E1×2E2,模数比结果类型中可表示的最大值减1。否则,如果E1具有有符号类型和非负值,并且在结果类型中可以表示E1×2E2,那么这就是结果值;否则,行为未定义。

3 The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a non-negative value, the value of the result is the integral part of the quotient of E1/2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

3 E1 >> E2的值是E1右移E2位的位置。如果E1具有无符号类型或者E1具有带符号类型和非负值,则结果的值是E1 / 2E2的商的整数部分。如果E1具有带符号类型和负值,则结果值是实现定义的。

For the same reason, I would think the bitwise and, or and negate are okay: they are defined mathematically.

出于同样的原因,我认为按位和/或否定是可以的:它们是数学定义的。

5.3.1 Unary operators [expr.unary.op]

5.3.1一元运算符[expr.unary.op]

10 The operand of ˜ shall have integral or unscoped enumeration type; the result is the one’s complement of its operand.

10~的操作数应具有整数或无范围的枚举类型;结果是其操作数的一个补码。

5.11 Bitwise AND operator [expr.bit.and]

5.11按位AND运算符[expr.bit.and]

1 The usual arithmetic conversions are performed; the result is the bitwise AND function of the operands. The operator applies only to integral or unscoped enumeration operands.

1执行通常的算术转换;结果是操作数的按位AND功能。运算符仅适用于整数或无范围的枚举操作数。

5.13 Bitwise inclusive OR operator [expr.or]

5.13按位包含OR运算符[expr.or]

1 The usual arithmetic conversions are performed; the result is the bitwise inclusive OR function of its operands. The operator applies only to integral or unscoped enumeration operands.

1执行通常的算术转换;结果是其操作数的按位包含OR函数。运算符仅适用于整数或无范围的枚举操作数。

However I will admit I am less sure for the latter two, I could not find any definition of bitwise XX function, so even though I believe they refer to they mathematical counterparts I can offer no assurance.

但是我承认我对后两者不太确定,我找不到任何按位XX函数的定义,所以即使我相信它们指的是数学对应物,我也无法保证。

(*) Thanks to phresnel for pointing that out.

(*)感谢phresnel指出这一点。

#2


5  

Unless some_unsigned_type is a fixed-width type, this is your first platform specific. On one platform, you may be shifting out some information that can never recur by the value itself, while on another it may not. Example:

除非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

5.8 Shift Operators in the C++ standard also says this:

5.8 C ++标准中的Shift运算符也说明了这一点:

The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.

如果右操作数为负数,或者大于或等于提升左操作数的位长度,则行为未定义。

So if you shift an integer by more bits than there are, you enter undefined behaviour. E.g., if you left-shift a short value by 17 bits, it may give you UB on some machines, but not all.

因此,如果将整数移位的位数多于输入的位数,则输入未定义的行为。例如,如果你将一个短值左移17位,它可能会在某些机器上给你UB,但不是全部。

C11 says in 6.5.7 Bitwise shift operators, apart from other things, this:

C11在6.5.7比特移位算子中说,除了其他东西,这个:

The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

E1 >> E2的结果是E1右移E2位的位置。如果E1具有无符号类型或者E1具有有符号类型和非负值,则结果的值是E1 / 2E2的商的整数部分。如果E1具有带符号类型和负值,则结果值是实现定义的。

So signed-number shifting is not portable.

因此,签名号码转换不可移植。

So, the general answer for integers in general is:

因此,整数的一般答案是:

Bitwise manipulations on integers are not portable.

#3


1  

It's implementation specific if you shift negative (or signed) numbers (through most implementations are the same U2 thing). It's portable for most uses if you shift unsigned numbers by values not exceeding the number of bits in variable.

如果你转移负数(或签名)数字(通过大多数实现是相同的U2事物),它是特定的实现。如果您将无符号数字移动不超过变量中位数的值,则它对于大多数用途都是可移植的。

#1


4  

Disclaimer: I am implicitly assuming that you are talking about an integer type with a fixed width. Bit-shifting otherwise is quite hazardous...

免责声明:我隐含地假设您正在谈论具有固定宽度的整数类型。否则,位移非常危险......

Standard: n3337 C++11

标准:n3337 C ++ 11

The definition of shifts is mathematical for unsigned types or positive values in signed types (*), and therefore not affected by the underlying hardware representation.

对于无符号类型或有符号类型(*)中的正值,移位的定义是数学的,因此不受底层硬件表示的影响。

5.8 Shift operators [expr.shift]

5.8移位运算符[expr.shift]

2 The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are zero-filled. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. Otherwise, if E1 has a signed type and non-negative value, and E1×2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

2 E1 << E2的值是E1左移E2位的位置;空位是零填充的。如果E1具有无符号类型,则结果的值为E1×2E2,模数比结果类型中可表示的最大值减1。否则,如果E1具有有符号类型和非负值,并且在结果类型中可以表示E1×2E2,那么这就是结果值;否则,行为未定义。

3 The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a non-negative value, the value of the result is the integral part of the quotient of E1/2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

3 E1 >> E2的值是E1右移E2位的位置。如果E1具有无符号类型或者E1具有带符号类型和非负值,则结果的值是E1 / 2E2的商的整数部分。如果E1具有带符号类型和负值,则结果值是实现定义的。

For the same reason, I would think the bitwise and, or and negate are okay: they are defined mathematically.

出于同样的原因,我认为按位和/或否定是可以的:它们是数学定义的。

5.3.1 Unary operators [expr.unary.op]

5.3.1一元运算符[expr.unary.op]

10 The operand of ˜ shall have integral or unscoped enumeration type; the result is the one’s complement of its operand.

10~的操作数应具有整数或无范围的枚举类型;结果是其操作数的一个补码。

5.11 Bitwise AND operator [expr.bit.and]

5.11按位AND运算符[expr.bit.and]

1 The usual arithmetic conversions are performed; the result is the bitwise AND function of the operands. The operator applies only to integral or unscoped enumeration operands.

1执行通常的算术转换;结果是操作数的按位AND功能。运算符仅适用于整数或无范围的枚举操作数。

5.13 Bitwise inclusive OR operator [expr.or]

5.13按位包含OR运算符[expr.or]

1 The usual arithmetic conversions are performed; the result is the bitwise inclusive OR function of its operands. The operator applies only to integral or unscoped enumeration operands.

1执行通常的算术转换;结果是其操作数的按位包含OR函数。运算符仅适用于整数或无范围的枚举操作数。

However I will admit I am less sure for the latter two, I could not find any definition of bitwise XX function, so even though I believe they refer to they mathematical counterparts I can offer no assurance.

但是我承认我对后两者不太确定,我找不到任何按位XX函数的定义,所以即使我相信它们指的是数学对应物,我也无法保证。

(*) Thanks to phresnel for pointing that out.

(*)感谢phresnel指出这一点。

#2


5  

Unless some_unsigned_type is a fixed-width type, this is your first platform specific. On one platform, you may be shifting out some information that can never recur by the value itself, while on another it may not. Example:

除非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

5.8 Shift Operators in the C++ standard also says this:

5.8 C ++标准中的Shift运算符也说明了这一点:

The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.

如果右操作数为负数,或者大于或等于提升左操作数的位长度,则行为未定义。

So if you shift an integer by more bits than there are, you enter undefined behaviour. E.g., if you left-shift a short value by 17 bits, it may give you UB on some machines, but not all.

因此,如果将整数移位的位数多于输入的位数,则输入未定义的行为。例如,如果你将一个短值左移17位,它可能会在某些机器上给你UB,但不是全部。

C11 says in 6.5.7 Bitwise shift operators, apart from other things, this:

C11在6.5.7比特移位算子中说,除了其他东西,这个:

The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

E1 >> E2的结果是E1右移E2位的位置。如果E1具有无符号类型或者E1具有有符号类型和非负值,则结果的值是E1 / 2E2的商的整数部分。如果E1具有带符号类型和负值,则结果值是实现定义的。

So signed-number shifting is not portable.

因此,签名号码转换不可移植。

So, the general answer for integers in general is:

因此,整数的一般答案是:

Bitwise manipulations on integers are not portable.

#3


1  

It's implementation specific if you shift negative (or signed) numbers (through most implementations are the same U2 thing). It's portable for most uses if you shift unsigned numbers by values not exceeding the number of bits in variable.

如果你转移负数(或签名)数字(通过大多数实现是相同的U2事物),它是特定的实现。如果您将无符号数字移动不超过变量中位数的值,则它对于大多数用途都是可移植的。