Deep C Dives: Bits!
Written by Mike James   
Wednesday, 09 April 2025
Article Index
Deep C Dives: Bits!
The Bitwise Operators
A Single Function To Write Bits

Bits - this is what programming is all about but how do you actually work with bits? Find out in this extract from my latest book Deep C Dives.

Deep C Dives
Adventures in C

By Mike James

Cdive360

Buy from Amazon.

Contents

Preface
Prolog C
Dive

  1. All You Need Are Bits
  2. These aren’t the types you’re looking for
  3. Type Casting
  4. Expressions
  5. Bits and More Bits
        Extract:
    Bits! ***NEW!
  6. The Brilliant But Evil for 
  7. Into the Void 
  8. Blocks, Stacks and Locals
  9. Static Storage
  10. Pointers
  11. The Array and Pointer Arithmetic
  12. Heap, The Third Memory Allocation
  13. First Class Functions
        Extract:
    First Class Functions
  14. Structs and Objects
  15. The Union
  16. Undefined Behavior
  17. Exceptions and the Long Jump

Dive 5

Bits and More Bits

All of the books in the world contain no
more information than is broadcast
as video in a single large American city in a single year.
Not all bits have equal value.

Carl Sagan

 

It really is all about bits and nothing matters more to the C programmer. When using other languages you can abstract away so far from reality that you can forget that bits exist at all. Of course, the fact that you choose C means that this isn’t what you want to do. If you are programming hardware or interacting with the operating system, individual bits are often the focus of your attention and working with them brings us to the subject of bit manipulation.

Addressing the Bit

You might think that there would be a direct way of getting at bits, but there isn’t. The reason is simply that hardware generally accesses a group of bits at a time. The memory is divided into locations, each of which corresponds to a fixed number of bits at a specific address. That is, when you supply a memory address you specify a group of bits – an address rarely specifies a particular bit. You could build a single-bit-wide computer, but it would be very slow and not particularly practical. For reasons of history, the smallest addressable group of bits is generally a byte, i.e. 8 bits, but again there is no theoretical reason for this, it is just a reasonable number to work with. The most commonly encountered hardware, x86/64 and ARM, use byte addressing, but they may well actually work with the memory in larger chunks. A commonly used nomenclature is:

byte = 8 bits

word = 2 bytes = 16 bits

double word = 4 bytes = 32 bits

quad word = 8 bytes = 64 bits

but this use isn’t universal and isn’t the subject of a standard so you always need to check in any given situation.

The whole question of how addressing actually works and what is efficient is very dependent on the hardware in use. The implementation of a memory cache also complicates things in that typically 8-byte, double words, are read and written to memory irrespective of the addressing mode in operation. In other words, you might think you are reading or writing a byte, word or double word but the hardware will do what it does to be efficient and does its best to keep this hidden from you.

What all this means is that you cannot reason in the abstract about what might be the most efficient way to read some bits. There may be no simple answer to which is faster – byte access, word access, double word access or quad word access – because the memory architecture of the machine may not be as important as the size and type of cache in use. For example, in most cases reading bytes sequentially will be faster than reading bytes that are separated in memory by eight or sixteen bytes. The reason is that sequential bytes generally can be read from the cache without having to reload, but well-spaced reads might trigger a cache reload on each operation. Even this isn’t certain because it depends on how full the cache is and how much free space there is.

If you are concerned about speed of access to a group of bytes, the only way to find out is to run a benchmark. You cannot deduce the performance from simple consideration of the addressing mode. This said, there is often a need to align an address with a word or double word boundary. For example if the address starts at 0 then the next byte is at address 1, the next word is at 2, the next double word is at 4 and the next quad word is at 8 and in general words start on addresses divisible by 2, double words divisible by 4 and quad words divisible by 8.



Last Updated ( Wednesday, 09 April 2025 )