471,073 Members | 1,496 Online

# portable bit ops

How portable are direct bit operations? Which ones are portable?
I have never bothered learning such low-level stuff (I have an excuse: I am
not a professional programmer), so I really don't know.

One thing I noticed while reading C code was that many C programmers seem to
be addicted to bit ops. After all using "bool" is such a waste of mem if you
can squeeze 8, 16, 32, whatever boolean values into a single integer type.
Especially some C programs like data compressors seem to consist of almost
nothing but bit ops. Now, many of these programs are very portable, so I
guess you can do such low-level hackery without abandoning portability. I am
thinking about starting to make use of bit ops myself, but I do not want to
lose platform independence, so which bit ops are safe?
Is there a tutorial for this stuff?

(Note: I have used the "bool squeeze" and shifting to replace
multiply/division tricks myself before, but I was never sure about how
portable the code was.)

copx
Apr 3 '07 #1
5 1698
copx wrote:
How portable are direct bit operations?
what are "direct bit operations"?

do you mean the operators |, &, ^, ! << and >>
Which ones are portable?
all of them if used correctly. Do bit operations on unsigned types.
Don't make assumtions about the size of types (a char may *not*
be 8 bits).

unsigned char c;
c = get_bits();
c &= 0xff; /* limit to 8 bits */

don't shift by values greater than the word size.
I have never bothered learning such low-level stuff (I have an excuse: I am
not a professional programmer), so I really don't know.
it depends what sort of programming you do. I use very little floating
point.
One thing I noticed while reading C code was that many C programmers seem to
can't say I'd noticed.

After all using "bool" is such a waste of mem if you
can squeeze 8, 16, 32, whatever boolean values into a single integer type.
depends how many booleans you have. Note the cost of getting the bits
in
and out may make your program slower (or even make it bigger!)

Especially some C programs like data compressors seem to consist of almost
nothing but bit ops.
err... and this came as a surprise to you? You are trying to pack,
say,
characters into less than their normal space, it isn't surprising you
have to
resort to accessing units smaller than characters.

Suppose your data is known to be all ASCII and ASCII is a 7-bit code.
You are
wasting one bit for every character stored. So you take the bottom
seven bits
of the first char and you put it in the first available 7 bits in the
output. I submit
you are probably going to end with some bit operations here.

Encrytion uses a lot of bit banging as well.
Now, many of these programs are very portable, so I
guess you can do such low-level hackery without abandoning portability. I am
thinking about starting to make use of bit ops myself, but I do not want to
lose platform independence, so which bit ops are safe?
Is there a tutorial for this stuff?

(Note: I have used the "bool squeeze" and shifting to replace
multiply/division tricks myself before, but I was never sure about how
portable the code was.)
I'm not sure it will even save you time. Before you start doing
"tricks" like this.
1. make sure your code is correct
2. measure it and find out if it is quick enough
3. find where it spends the time
4. make that faster
5. re-measure

it hardly ever pays to transform
i * 8
into
i << 3
an excercise for you, print out the binary expansion of a number
putbin(0x7a)

produces
01111010
--
Nick Keighley

What goes "Pieces of Seven! Pieces of Seven!"?
A Parroty Error.

Apr 3 '07 #2
Nick Keighley <ni******************@hotmail.comwrote:
don't shift by values greater than the word size.
Don't you mean greater than or equal? If `i' is an unsigned 32-bit integral,
it's _not_ specified what this computes to: i >32.

IIRC, on an x86, if the least significant bit was 1, a right shift of 32
would set the most significant bit to 1. I learned this the hard way.
Apr 3 '07 #3
copx <co**@gazeta.plwrote:
How portable are direct bit operations? Which ones are portable?
I have never bothered learning such low-level stuff (I have an excuse: I am
not a professional programmer), so I really don't know.
You seem to be heading down the same, and wrong, path, that many
"professional" programmers have before you ;)

All operations, including bit operators, operate on the _logical_ values.
Lack of code portability is almost always an artifact of a programmer
forgetting or being ignorant of this fact (or maybe just asking for
trouble).

In C, almost by definition you never need (or should) care about how values
are represented in hardware. All you know is that you're given some
tools--operators and a language specification--that tell you how to
manipulate those values.

Bit operations required because you need to shuffle bytes based on
"little-endianness", etc, come from externalities. Even then, one only need
concern their self w/ the arrangement of the input, not w/ the destination
data object. Thus, if you somehow get a 4-byte "big-endian" from outside the
application, the following code is always portable:

/*
Filled from an fread() or some such mechanism. We're assuming
that each byte of data came in 4 8-bit units, and that our input
mechanism placed each 8-bit unit consecutively into one of the 4
array elements. Since it's "big-endian", the most signifiant byte
was read first, and is the first array element.
*/
unsigned char buf[4] = { 0x01, 0x00, 0x00, 0x00 };
unsigned long lu;

lu = ((unsigned long)buf[0] << (8 * 3))
| ((unsigned long)buf[1] << (8 * 2))
| ((unsigned long)buf[2] << (8 * 1))
| ((unsigned long)buf[3] << (8 * 0));

/*
This condition should _always_ be true, regardless of your platform.
Even if you're on one of the fabled DSP chips where (unsigned char)
is 16 bits.
*/
if (lu == 16777216) {
...
}
The mistake some programmers often make is to do something like the
following (note that I'm being generous, because their code is often much
more terse, assumes that CHAR_BIT is 8 w/o checking, and will often use
(unsigned long) assuming it to be 32-bits):

#include <stdint.h/* uint32_t */
#include <limits.h/* CHAR_BIT */

unsigned char srcbuf[4] = { 0x01, 0x00, 0x00, 0x00 };
unsigned char dstbuf[4];
uint32_t lu;

#if OUR_MACHINE_IS_LITTLE_ENDIAN
dstbuf[1] = srcbuf[3];
dstbuf[0] = srcbuf[2];
dstbuf[3] = srcbuf[1];
dstbuf[2] = srcbuf[0];
#else
(void)memcpy(dstbuf, srcbuf, sizeof dstbuf);
#endif

#if CHAR_BIT = 8
(void)memcpy(&lu, dstbuf, sizeof lu);
#else
#error Want CHAR_BIT to be 8
#endif

Apr 3 '07 #4
On Tue, 3 Apr 2007 10:48:20 +0200, "copx" <co**@gazeta.plwrote in
comp.lang.c:
How portable are direct bit operations? Which ones are portable?
I have never bothered learning such low-level stuff (I have an excuse: I am
not a professional programmer), so I really don't know.

One thing I noticed while reading C code was that many C programmers seem to
be addicted to bit ops. After all using "bool" is such a waste of mem if you
can squeeze 8, 16, 32, whatever boolean values into a single integer type.
Especially some C programs like data compressors seem to consist of almost
nothing but bit ops. Now, many of these programs are very portable, so I
guess you can do such low-level hackery without abandoning portability. I am
thinking about starting to make use of bit ops myself, but I do not want to
lose platform independence, so which bit ops are safe?
Is there a tutorial for this stuff?

(Note: I have used the "bool squeeze" and shifting to replace
multiply/division tricks myself before, but I was never sure about how
portable the code was.)

copx
A large percentage of the code I wrote for a chapter in the book "C
Unleashed" uses bit operations quite heavily. The code for encoding
and decoding fax data, and for parity, hamming, and CRC, would all be
pretty much impossible without it.

The most intensive use of bit fields and bit shifting is in the fax
encode and decode routines. The codes for various numbers of black
and white pixels in fax encoding are different length bit strings.

All of the fax code is completely portable because, as another poster
pointed out, if uses unsigned chars and only the 8 least significant
bits of each byte, even on a platform with more than 8 bits per byte.

The text of the book belongs to the publisher, and so is not available
on my web site, but the code, which is under GPL, is.

Take a look as http://jk-technology.com/C_Unleashed/code_list.html and
see if anything interests you.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html
Apr 4 '07 #5

"copx" <co**@gazeta.plschrieb im Newsbeitrag
news:eu**********@inews.gazeta.pl...
How portable are direct bit operations? Which ones are portable?
I have never bothered learning such low-level stuff (I have an excuse: I
am not a professional programmer), so I really don't know.
[snip]

Thanks everyone!

copx
Apr 4 '07 #6

### This discussion thread is closed

Replies have been disabled for this discussion.