SandBag_1996
SandBag_1996

Reputation: 1601

Bit field manipulation

In the following code

#include <iostream>

using namespace std;
struct field
{
   unsigned first : 5;
   unsigned second : 9;
};
int main()
{
   union
   {
      field word;
      int i;
   };
   i = 0;
   cout<<"First is : "<<word.first<<" Second is : "<<word.second<<" I is "<<i<<"\n";
   word.first = 2;
   cout<<"First is : "<<word.first<<" Second is : "<<word.second<<" I is "<<i<<"\n";
   return 0;
}

when I initialize word.first = 2, as expected it updates 5-bits of the word, and gives the desired output. It is the output of 'i' that is a bit confusing. With word.first = 2, i gives output as 2, and when I do word.second = 2, output for i is 64. Since, they share the same memory block, shouldnt the output (for i) in the latter case be 2?

Upvotes: 2

Views: 216

Answers (2)

rmhartog
rmhartog

Reputation: 2323

While this depends on both your platform and your specific compiler, this is what happens in your case:

The union overlays both the int and the struct onto the same memory. Let us assume, for now, that your int has a size of 32 bits. Again, this depends on multiple factors. Your memory layout will look something like this:

IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
                  SSSSSSSSSFFFFF

Where I stands for the integer, S for the second field and F for the first field of your struct. Note that I have represented the most significant bit on the left.

When you initialize the integer to zero, all the bits are set as zero, so first and second are also zero. When you set word.first to two, the memory layout becomes:

00000000000000000000000000000010
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
                  SSSSSSSSSFFFFF

Whichs leads to a value of 2 for the integer. However, by setting the value of word.second to 2, the memory layout becomes:

00000000000000000000000001000000
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
                  SSSSSSSSSFFFFF

Which gives you a value of 64 for the integer.

Upvotes: 1

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272487

This particular result is platform-specific; you should read up on endianness.

But to answer your question, no, word.first and word.second don't share memory; they occupy separate bits. Evidently, the underlying representation on your platform is thus:

bit   15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
     |     |         second           |    first     |
     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
     |<------------------- i ----------------------->|

So setting word.second = 2 sets bit #6 of i, and 26 = 64.

Upvotes: 7

Related Questions