bitwise operator and endianness

Discussion in 'C Programming' started by Rahul, Nov 5, 2007.

1. RahulGuest

Hi Everyone,

I have a program unit which does >> and << of an integer which is of
4 bytes length. The logic of shifting and action based on the result,
assumes that the system is big-endian.

Accordingly, if i need the program to work fine in a little-endian
system. I understand that the code needs to be changed. ( I couldn't
find any statement in C90 about endianness, hence i'm assuming that c
programs are not portable if the endianness of the system changes)

I wanted to know if the above holds true for bitwise and (&) and
bitwise or (|). I think, the system should take care of the
operation a&b or a|b irrespective of the endianness of the system.

Rahul, Nov 5, 2007

2. James KuyperGuest

The appropriate fix depends upon the way in which that assumption is
built into the code. Endianness only matters if a) you're sharing data
between systems with different endianness or b) you're accessing the
integer as a array of unsigned char. Could you indicate exactly how the
code makes that assumption? Please give actual code, but simplified down
to it's essential elements.

James Kuyper, Nov 5, 2007

3. Chris DollinGuest

Well, no, I rather suspect it doesn't. What it /does/ depend on is
how you've chosen to represent the fields in the integer, and how
you get them in there.

How are you representing the fields in the integer, and how do
you get them in there? Show real, minimal, code.

Chris Dollin, Nov 5, 2007
4. peteGuest

No it doesn't.
Any positive value, right shifted by one, has the same result
as if that positive value were divided by two instead.

pete, Nov 5, 2007
5. Eric SosmanGuest

Thought experiment:

int i = 42;
int j = i * 2;
int k = i << 1;
assert (j == k);

Can the assert() fail? If so, what does it tell you about
the system's endianness? If not, what does it tell you about
the *influence* of the system's endianness?

Eric Sosman, Nov 5, 2007
6. Martin AmbuhlGuest

The shift operators act on values, not bit patterns. This may seem
confusing, I know. But the fact is that if you depend on the particular
form of storage, then you are dealing with implementation-specific
behavior.

Similarly, if you depend on, for example, using a specific size unsigned
integer to shift left and then right to zero out the more significant
bits, your program will not be portable. Nor will it be portable if you
attempt to shift values greater than the equivalent of the number of
bits in the type (or by negative numbers of bits). Nor will it be
portable if the left operand is a negative signed value and the right
operand is non-zero.

Now, "4 bytes length" is not useful information here. If CHAR_BIT is 8,
then the relevant value is "32 bits". The only types for which << and unsigned long and unsigned long long. So your integer must not be of
type [signed or unsigned] x [char or short or int], nor can it be
possibly negative and signed long or signed long long.
If the _values_ are the salient feature of your integers, then your
programs will be portable as long as
1) the right operand is no longer than the minimum possible width of
the left operand and positive, and
2) the the left operand for >> is never a negative signed value with a
non-zero right operand.
But, if you want your code to be portable, use only unsigned operands.
And remember that any relevant testa should, in the usual case, not
require that the type of the tested operand be wider than the minimum
guaranteed by the standard.

Martin Ambuhl, Nov 5, 2007