Working with Bitfields
Given space is often at a premium when writing applications for mobile devices, I want to show you how to use bitfields to manage a series of values that need only on/off status. The upside is that you can store a surprising number of status values within a single integer, 32 to be exact.
The code that follows is pure C. Given that Objective-C is a superset of C, don’t forget that you can leverage all that C has to offer, beyond working with objects.
1 2 3 4 5 6 | struct { unsigned preLoaded: 1; unsigned saveState: 1; unsigned saveLoginName: 1; } statusFlags; |
I’ve defines three bitfields, all which will be saved within an unsigned integer. Accessing the bits is as easy as this:
1 2 3 4 5 6 7 | // Setting bits statusFlags.preLoaded = 1; statusFlags.saveState = statusFlags.saveLoginName = 0; // Get bits if (statusFlags.saveLoginName == 0) ... do something here... |
Using the sizeof() function, let’s compare the size of an integer to the size of the structure we created:
1 2 3 4 5 6 7 8 9 10 11 12 | // Setting bits statusFlags.preLoaded = 1; statusFlags.saveState = statusFlags.saveLoginName = 0; // Get bits if (statusFlags.saveLoginName == 0) NSLog(@"saveLoginName bit is on."); else NSLog(@"saveLoginName bit is off."); NSLog(@"Sizeof int: %d", sizeof(int)); NSLog(@"Sizeof statusFlags: %d", sizeof(statusFlags)); |
The output looks as follows, which verifies that the bitfields are maintained within a single unsigned integer.

What’s interesting is that we now know that an integer is 4 bytes, this would imply that we can store up to 32 separate flags within our structure. To verify this the case, let’s create a new structure that looks as follows:
1 2 3 4 5 6 7 8 | struct { unsigned preLoaded: 1; unsigned saveState: 1; unsigned saveLoginName: 1; unsigned buffer: 28; unsigned savePassword: 1; } statusFlagsExtended; |
In this structure, ‘buffer’ is nothing more than a means for me to soak up 28 bits such that I can add one more bit on the end. Let’s take a look at the sizeof this structure with the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 | // Setting bits statusFlags.preLoaded = 1; statusFlags.saveState = statusFlags.saveLoginName = 0; // Get bits if (statusFlags.saveLoginName == 0) NSLog(@"saveLoginName bit is on."); else NSLog(@"saveLoginName bit is off."); NSLog(@"Sizeof int: %d", sizeof(int)); NSLog(@"Sizeof statusFlags: %d", sizeof(statusFlags)); NSLog(@"Sizeof statusFlagsExtended: %d", sizeof(statusFlagsExtended)); |
As expected, the structure ‘statusFlagsExtended’ is also stored as an integer.

Even thought the bulk of developing iPhone application is all about Objective-C, don’t forget to lean on C as needed to get the job done.








Nice article. I didn’t realize that a struct could be use like this. What I would like to know more about though, is how this could be applied to custom binary data downloaded via the network.
Imagine a custom network protocol in which a sequence of bytes where downloaded and each byte had meaning. How would one read those bytes? I’d assume you would start with NSData, convert that into a char[] and then create a pointer to move through the char array. Each char, being one byte, would then need to be masked to get the value for a particular bit in the byte.
A good example of this applied is WBXML, which is a way to encode XML into a very compact binary protocol. XML documents will, on average, will be 60% smaller when encoded as WBXML, which when gzip’d on top of that you can get some amazing compression.
Very nice article!
This is a very clean and compact approach to a type of data structure I seem to find myself needing time and time again. Anxious to give it a go today!
Rodney, Using C sockets you can actually just do a straight send/receive of the struct. Pseudo code to follow:
typedef struct
{
unsigned preLoaded: 1;
unsigned saveState: 1;
unsigned saveLoginName: 1;
} statusFlags;
// Setup send socket
send(statusFlags)
// Setup receive socket
int count = receive()
if( count > 0 )
{
statusFlags flags = ( statusFlags *)buffer;
}
But i think it is not guaranteed that the compiler decides to pack them like this he might decide to align every bit to a byte adress for performance reasons.
Old versions of vc6 had to be set to explictly pack it using #pragma pack dont know about gcc though.
I think the most reliable solution is (memory << bitn) & mask.