Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Standard (cross-platform) way for bit manipulation

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

  • 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 :)

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

like image 672
Kiril Kirov Avatar asked Oct 04 '12 15:10

Kiril Kirov


1 Answers

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:

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:

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.

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

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.

So signed-number shifting is not portable.

So, the general answer for integers in general is:

Bitwise manipulations on integers are not portable.

like image 133
Sebastian Mach Avatar answered Sep 28 '22 11:09

Sebastian Mach