Is a field more efficient (in terms of calculation) than the masking bits and the data extraction by hand?

advertisements

I have a numerous small pieces of data that I want to be able to shove into one larger data type. Let's say that, hypothetically, this is a date and time. The obvious method is via a bit field like this.

struct dt
{
    unsigned long minute :6;
    unsigned long hour :5;
    unsigned long day :5;
    unsigned long month :4;
    unsigned long year :12;
}stamp;

Now let's pretend that this thing is ordered so that things declared first are at bits of higher significance than things declared later so if I represent the bits by the first letter of the variable it would look like:

mmmmmm|hhhhh|ddddd|mmmm|yyyyyyyyyyyy

Finally, let's pretend that I simply declare an unsigned long and split it up using masks and shifts to do the same things.

unsigned long dateTime;

Here is my question:
Are the following to methods of accessing minutes, hours, etc. equivalent in terms of what the computer needs to do? Or is there some tricksy method that the compiler/computer uses with the bit fields.

unsigned minutes = stamp.minutes;
//versus
unsigned minutes = ((dateTime & 0xf8000000)>>26;

and

unsigned hours = stamp.hours;
//versus
unsigned hours = ((dateTime & 0x07C00000)>>21;

etc.


The compiler generates the same instructions that you would explicitly write to access the bits. So don't expect it to be faster with bitfields.

In fact, strictly speaking with bitfields you don't control how they are positioned in the word of data (unless your compiler gives you some additional guarantees. I mean that the C99 standard doesn't define any). Doing masks by hand, you can at least place the two most often accessed fields first and last in the series, because in these two positions, it takes one operation instead of two to isolate the field.