Bit shifting vs Bitfields

R

richard_l

Hello All,

I am writing an application which receives a word which is a bitmap. I
have created a word typedef which contains a bitfield defining each
bit. however, I was wondering however if it would be better to write a
macro to access each bit instead of the bitfield.

I have read the C-FAQ on bit fields, but was wondering if there were
any advantages/disadvantages to using bit shifting. To my mind I think
using bitfields are more logical and easier to read and use but have a
feeling it is slower than bit shifting.

Can anyone enlighten me on this subject?

Regards,

Richard
 
I

Ian Collins

Hello All,

I am writing an application which receives a word which is a bitmap. I
have created a word typedef which contains a bitfield defining each
bit. however, I was wondering however if it would be better to write a
macro to access each bit instead of the bitfield.

I have read the C-FAQ on bit fields, but was wondering if there were
any advantages/disadvantages to using bit shifting. To my mind I think
using bitfields are more logical and easier to read and use but have a
feeling it is slower than bit shifting.
Don't speculate, profile!

I'm a bit field fan for the reasons you mention and whenever I've
bothered to look, the compiler generated very tight code to access them.

Just make sure you don't run into any endian issues.
 
J

Jack Klein

Hello All,

I am writing an application which receives a word which is a bitmap. I
have created a word typedef which contains a bitfield defining each
bit. however, I was wondering however if it would be better to write a
macro to access each bit instead of the bitfield.

Maybe it would, maybe not.
I have read the C-FAQ on bit fields, but was wondering if there were
any advantages/disadvantages to using bit shifting. To my mind I think
using bitfields are more logical and easier to read and use but have a
feeling it is slower than bit shifting.

Why do you care which method is faster or slower? You shouldn't care
at all until the following program returns TRUE:

enum { FALSE, TRUE } BOOL;

BOOL should_I_worry_about_speed(void)
{
BOOL result = FALSE;

if (this_part_of_my_program_is_tested_and_verified_correct()
&& my_program_is_finished_and_works_correctly()
&& my_correct_program_runs_too_slowly()
&& I_have_verified_this_code_is_a_bottleneck())
/* then and only then */
{
result = TRUE;
}

return result;
}

Of course, you need to implement the four functions called. Or even
better, treat this as pseudo code and just answer the questions
yourself. If, and only if, the answers to all four questions are
true, then you can start thinking, and testing, whether bit fields are
faster than bit masks, or vice-versa.
Can anyone enlighten me on this subject?

Even if all the above answers are true, the only way to know whether
bit fields or bit masks are faster on your particular compiler and
processor is to build test code both ways and time it.

I have seen processors that have machine language instructions that
support bit-field manipulation, and C compilers that use them, with
the result that code using bit fields executes faster than code using
bit masks. And I have seen platforms where the opposite is true.
 
M

Malcolm

Jack Klein said:
Why do you care which method is faster or slower? You shouldn't care
at all until the following program returns TRUE:

enum { FALSE, TRUE } BOOL;

BOOL should_I_worry_about_speed(void)
{
BOOL result = FALSE;

if (this_part_of_my_program_is_tested_and_verified_correct()
&& my_program_is_finished_and_works_correctly()
&& my_correct_program_runs_too_slowly()
&& I_have_verified_this_code_is_a_bottleneck())
/* then and only then */
{
result = TRUE;
}

return result;
}

Of course, you need to implement the four functions called. Or even
better, treat this as pseudo code and just answer the questions
yourself. If, and only if, the answers to all four questions are
true, then you can start thinking, and testing, whether bit fields are
faster than bit masks, or vice-versa.


Even if all the above answers are true, the only way to know whether
bit fields or bit masks are faster on your particular compiler and
processor is to build test code both ways and time it.

I have seen processors that have machine language instructions that
support bit-field manipulation, and C compilers that use them, with
the result that code using bit fields executes faster than code using
bit masks. And I have seen platforms where the opposite is true.
Bitfields were once generally badly implemented.
There was a kind of vicious circle. Programmers used masks because the
bitfield code was slow, and complier writers didn't bother much to optimise
bitfields because they were rarely used.

I am sure whether this is still the case. Now that memory sizes are so
large, usually it doesn't make much sense to try to squash data into a
minimal number of bits.
 
S

swengineer001

Malcolm said:
Bitfields were once generally badly implemented.
There was a kind of vicious circle. Programmers used masks because the
bitfield code was slow, and complier writers didn't bother much to optimise
bitfields because they were rarely used.

I am sure whether this is still the case. Now that memory sizes are so
large, usually it doesn't make much sense to try to squash data into a
minimal number of bits.

When I have used bit fields it has usually been to overlay a structure
on a register of some sort, i.e. status register, where certain bits or
groups of bits have certain meanings. To my mind this makes the code
much more readable. This sort of thing has nothing to do with memory
footprint.
 
W

Walter Roberson

When I have used bit fields it has usually been to overlay a structure
on a register of some sort, i.e. status register, where certain bits or
groups of bits have certain meanings. To my mind this makes the code
much more readable.

Bit-mapped registers are often defined in terms of value bits, but
bit fields are not, leading to a potential endian confusion and
non-portability.

On the other hand, status registers are not portable anyhow ;-)
 
S

swengineer001

Walter said:
Bit-mapped registers are often defined in terms of value bits, but
bit fields are not, leading to a potential endian confusion and
non-portability.

On the other hand, status registers are not portable anyhow ;-)

Yeah, in order for my code to need to be portable the custom ASIC will
need a respin. I don't see anyone spending the money on that and even
if they do they are likely not to change the processor due to the large
amount of existing code.
 
R

richard_l

Hello All,

Many thanks for the advice given. I was aware of the endian issue
before I posted this. My main query was if there were any benefits to
bit shifting rather than defining bit fields. I think my conclusion is
that unless you are porting code, defining bitfields are fine. I
would suggest that most ANSI compilers these days (I'm using gcc)
handle bitfields in the appropriate manner.

Thanks for all the contributions,

Regards,

Richard
 
R

Roberto Waltman

bit shifting rather than defining bit fields. I think my conclusion is
that unless you are porting code, defining bitfields are fine. I
would suggest that most ANSI compilers these days (I'm using gcc)
handle bitfields in the appropriate manner.

I agree with the "appropriate handling", but not with "bit fields
unless porting".

I would use bit fields only if all of the following three assumptions
are true:

(a) It does not matter what bits are assigned to which field. [1]
(b) The size of the structure containing the bit fields is not
important. [2]
(c) The alignment of a bit field structure is not important. [3]

In most cases they are not, so I use masks + shifts.



(*) ISO/IEC 9899:1999(E):
6.7.2.1 Structure and union specifiers
....
Constraints
10 [2] An implementation may allocate any addressable storage unit
large enough to hold a bitfield.
If enough space remains, a bit-field that immediately follows another
bit-field in a structure shall be packed into adjacent bits of the
same unit. [2] If insufficient space remains, whether a bit-field that
does not fit is put into the next unit or overlaps adjacent units is
implementation-defined. [1] The order of allocation of bit-fields
within a unit (high-order to low-order or low-order to high-order) is
implementation-defined. [3] The alignment of the addressable storage
unit is unspecified.
 
P

pete

Roberto Waltman wrote:
I would use bit fields only if all of the following three assumptions
are true:

(a) It does not matter what bits are assigned to which field. [1]
(b) The size of the structure containing the bit fields is not
important. [2]
(c) The alignment of a bit field structure is not important. [3]

In most cases they are not, so I use masks + shifts.

But even in cases when they are, those three conditions
don't supply a reason not to use masks and shifts,
so I always use masks and shifts.
 
I

Ian Collins

Roberto said:
bit shifting rather than defining bit fields. I think my conclusion is
that unless you are porting code, defining bitfields are fine. I
would suggest that most ANSI compilers these days (I'm using gcc)
handle bitfields in the appropriate manner.


I agree with the "appropriate handling", but not with "bit fields
unless porting".

I would use bit fields only if all of the following three assumptions
are true:

(a) It does not matter what bits are assigned to which field. [1]
(b) The size of the structure containing the bit fields is not
important. [2]
(c) The alignment of a bit field structure is not important. [3]

In most cases they are not, so I use masks + shifts.
Have you ever come across a real world situation where any of these are
an issue?
 
W

Walter Roberson

Roberto Waltman wrote:
Have you ever come across a real world situation where any of these are
an issue?

Yes...

20-ish years ago, I did a debugger/disassembler. The bit order
was important because some of the bits came from outside my control.
If I had programmed in terms of bitfields then the program would
have relied upon implementation-dependant behaviour.

But for my purposes, it turned out to be easier to write the code
in a table-driven manner, with bit masks and comparison values,
so the issue was avoided -- almost accidently, you might say.

Later I ported the disassembler part of the code to handle a completely
different architecture. If I had written in terms of bitfields the first
time, I would have had to rewrite to suit the compiler on the new
architecture; as it was, it was just a matter of populating the
table entries and writing code to handle the new addressing modes.
The table-driven code was again easier to handle in terms of bitmasks.


Somewhere in there is a point or two ;-) That
(1) if you do not control the generation and storage of all the
data to be manipulated, then the bitfield order and sizing would
indeed be important;
(2) that bitmasks are often easier to write for, and the code
generalizes and simplifies more readily
 
R

Roberto Waltman

Ian Collins said:
Roberto said:
I would use bit fields only if all of the following three assumptions
are true:

(a) It does not matter what bits are assigned to which field. [1]
(b) The size of the structure containing the bit fields is not
important. [2]
(c) The alignment of a bit field structure is not important. [3]

In most cases they are not, so I use masks + shifts.
Have you ever come across a real world situation where any of these are
an issue?

In embedded systems and communication protocols, all the time.

If I need, (drawing an example from a real project,) to set one of the
hardware registers controlling a communications device, where bit 0 is
an enable/disable flag, and bits 1 and 2 select one of four available
transfer rates, there is no portable way to do it using bitfields.

Lets assume the register is 8 bits wide, and I am using a 32 bit
processor which can access 8, 16, and 32 bit "storage units"

This struct

struct com_ctrl
{
unsigned int e:1; /* enable and rate. using one letter */
unsigned int r:2; /* identifiers to fit in the */
}; /* diagrams below */

could be mapped into any of these:

7 6 5 4 3 2 1 0
+-+-+-+-+-+---+-+
| | | | | | r |e|
+-+-+-+-+-+---+-+

7 6 5 4 3 2 1 0
+-+---+-+-+-+-+-+
|e| r | | | | | |
+-+---+-+-+-+-+-+

15 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+-+-+-+-+-+-+-+-+-+-+-+-+-+---+-+
| | | | | | | | | | | | | | r |e|
+-+-+-+-+-+-+-+-+-+-+-+-+-+---+-+

15 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+-+---+-+-+-+-+-+-+-+-+-+-+-+-+-+
|e| r | | | | | | | | | | | | | |
+-+---+-+-+-+-+-+-+-+-+-+-+-+-+-+

31 0 9 8 7 6 ... 9 8 7 6 5 4 3 2 1 0
+-+-+-+-+-+-+ ... +-+-+-+-+-+-+-+---+-+
| | | | | | | ... | | | | | | | | r |e|
+-+-+-+-+-+-+ ... +-+-+-+-+-+-+-+---+-+

31 0 9 8 7 6 ... 9 8 7 6 5 4 3 2 1 0
+-+---+-+-+-+ ... +-+-+-+-+-+-+-+-+-+-+
|e| r | | | | ... | | | | | | | | | | |
+-+---+-+-+-+ ... +-+-+-+-+-+-+-+-+-+-+


Not only the bit positions may not match, it is also impossible to
copy such a structure into the control register without risking
modifying adjacent registers.
 
I

Ian Collins

Roberto said:
Ian Collins said:
Roberto said:
I would use bit fields only if all of the following three assumptions
are true:

(a) It does not matter what bits are assigned to which field. [1]
(b) The size of the structure containing the bit fields is not
important. [2]
(c) The alignment of a bit field structure is not important. [3]

In most cases they are not, so I use masks + shifts.

Have you ever come across a real world situation where any of these are
an issue?


In embedded systems and communication protocols, all the time.

If I need, (drawing an example from a real project,) to set one of the
hardware registers controlling a communications device, where bit 0 is
an enable/disable flag, and bits 1 and 2 select one of four available
transfer rates, there is no portable way to do it using bitfields.

Lets assume the register is 8 bits wide, and I am using a 32 bit
processor which can access 8, 16, and 32 bit "storage units"

This struct

struct com_ctrl
{
unsigned int e:1; /* enable and rate. using one letter */
unsigned int r:2; /* identifiers to fit in the */
}; /* diagrams below */

could be mapped into any of these:
But is it? I've never seen this happen with an embedded compiler. Bit
fields tend to be well documented in these..
 
R

Roberto Waltman

Ian Collins said:
....
But is it? I've never seen this happen with an embedded compiler. Bit
fields tend to be well documented in these..

I am not sure I understand you question. Any particular choice is
likely to be documented and stable for a particular compiler.
Any code relying on that choice is still not portable.

Use that communication device I used as an example in a different
product, with a different processor and compiler and the code may not
work anymore.

The same applies to the handling of fields in communication protocols
when messages are exchanged between separate processors.

The structure size problem can be a show stopper, documented or not.
 
K

Keith Thompson

Roberto Waltman said:
bit shifting rather than defining bit fields. I think my conclusion is
that unless you are porting code, defining bitfields are fine. I
would suggest that most ANSI compilers these days (I'm using gcc)
handle bitfields in the appropriate manner.

I agree with the "appropriate handling", but not with "bit fields
unless porting".

I would use bit fields only if all of the following three assumptions
are true:

(a) It does not matter what bits are assigned to which field. [1]
(b) The size of the structure containing the bit fields is not
important. [2]
(c) The alignment of a bit field structure is not important. [3]

*or*

The compiler precisely documents how it lays out bit fields, and I
know I'll never need to worry about portability to any other compiler
that doesn't make the same guarantees. Yes, masks and shifts will do
the same job, but bit fields are easier to work with.

(A good argument can be made that masks and shifts are a better idea
even in these circumstances.)
 
C

Chris Torek

Roberto said:
struct com_ctrl
{
unsigned int e:1; /* enable and rate. using one letter */
unsigned int r:2; /* identifiers to fit in the */
}; /* diagrams below */
could be mapped into [various pictures, snipped]

But is it?

I have written drivers for two particular chips (one AMD Ethernet
chip and one Zilog serial port chip) that have been used on MIPS
("both endian" and one of them had only 32-bit load/store), SPARC,
Intel, and other CPUs. These drivers did not use bitfields,
despite their apparent convenience, because those bitfields were
in fact mapped differently on those different machines.

In general, using bitfields buys you a little convenience, which
you later pay for in effort porting the driver to new compilers
and machines. Sometimes this tradeoff is worth it and sometimes
it is not.
 
I

Ian Collins

Keith said:
Roberto Waltman said:
(e-mail address removed) wrote:
My main query was if there were any benefits to
bit shifting rather than defining bit fields. I think my conclusion is
that unless you are porting code, defining bitfields are fine. I
would suggest that most ANSI compilers these days (I'm using gcc)
handle bitfields in the appropriate manner.

I agree with the "appropriate handling", but not with "bit fields
unless porting".

I would use bit fields only if all of the following three assumptions
are true:

(a) It does not matter what bits are assigned to which field. [1]
(b) The size of the structure containing the bit fields is not
important. [2]
(c) The alignment of a bit field structure is not important. [3]


*or*

The compiler precisely documents how it lays out bit fields, and I
know I'll never need to worry about portability to any other compiler
that doesn't make the same guarantees. Yes, masks and shifts will do
the same job, but bit fields are easier to work with.
That's been my situation, embedded targets where the toolchain is very
unlikely to change.
 
R

Roberto Waltman

Ian Collins said:
That's been my situation, embedded targets where the toolchain is very
unlikely to change.

OK, I get it now. I agree, the toolchain used for an embedded project
is not likely to change. My comments were in the context of code that
may be ported to different platforms. (Or, for communication
protocols, shared among different platforms.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top