0

Anytime structures are thrown inside other structures I just get confused for some reason. I'm writing a driver for a I2C (2-wire Serial Interface) device and I'm using the manufacturers drivers as a reference for creating mine. I have this union statement below (which is defined in a header file) and I just can't understand a few lines inside it. Just a brief background so you know what you're looking at is the main snippet below is setting up this TWI_statusReg variable which holds the information from a status register every time i'm transmitting/receiving data across the I2c bus. This data register is 8 bits long and belongs to a Atmel Atmega328P microcontroller. Here are my questions...

1.) Its hard to formulate this question in words but can you explain in easy terms of why you would declare a data struct inside a union struct like this? What key points should I pick out from this?

2.) In the ".c" header definition file which is too long to post here, there is a single line that says the following

TWI_statusReg.all = 0;

I know there is a char variable in the header file called 'all' as seen in the main snippet of code below. However, I'm not understanding what happens when it gets assigned a zero. Is this setting all the bits in the status register to zero?

3.) The two lines

unsigned char lastTransOK:1;
unsigned char unusedBits:7; 

are confusing to me specifically what the colon operator is doing.

The main snippet of CODE

/****************************************************************************
  Global definitions
****************************************************************************/

union TWI_statusReg                       // Status byte holding flags.
{
    unsigned char all;
    struct
    {
        unsigned char lastTransOK:1;      
        unsigned char unusedBits:7;
    };
};

extern union TWI_statusReg TWI_statusReg;
SCY
  • 35
  • 6
  • The colon operator specifies the number of bits used for that field. – Code-Apprentice Oct 08 '16 at 23:41
  • And bit-fields are non-portable. There's no platform-independent way that I'm aware of to know which bit of `all` corresponds to the `lastTansOK` bit. It could be the first bit, or it could be the last bit. And if you use a different compiler, it's likely to change. – Andrew Henle Oct 08 '16 at 23:50
  • 2
    If `TWI_statusReg.all = 0;` is in a header file (outside an `inline` function or a macro, it sheds a very bad light on the code quality. Your question is confused and unclear. Best is to get a C book and read the sections about `struct`s and `union`s. – too honest for this site Oct 08 '16 at 23:57
  • @AndrewHenle the following line gets used quite a bit in the existing driver........TWI_statusReg.lastTransOK = TRUE;........However, I see your point that there is no way to know. – SCY Oct 08 '16 at 23:58
  • @Code-Apprentice it's not an operator (operators operate on expressions) – M.M Oct 09 '16 at 00:06
  • @M.M Good point. I was in a bit of a hurry and just used the OPs wording. – Code-Apprentice Oct 09 '16 at 00:08
  • For unions vs. structs you might like to read around here: http://stackoverflow.com/q/346536/694576 – alk Oct 09 '16 at 10:31

1 Answers1

0

1) The main reason for writing such a union is convenience. Instead of doing manually bit masks every time you need to access specific bits, you now have aliases for those bits.

2) Unions let you refer to memory as if its components were different variables representing different types. Unions only allocate space for the biggest component inside them. So if you have

union Example {
      char bytes[3];
      uint32_t num;
};

such a union would take 4 bytes, since its biggest type uint32_t takes 4 bytes of space. It would probably make more sense to have a union like this though, since you're using that space anyway and it's more convenient:

union Example {
      char bytes[4];
      uint32_t num;
};

bytes array will let you access individual bytes of num.

Your guess is correct - writing value to all will set the corresponding bits of the union.

3) This construct is called a bit field, and is an optimization of memory usage - if you were to use a struct of 2 chars it would actually take 2 bytes of memory space, instead if you declare a bit field it will only take 1 byte (and you still have 6 more "unused" bits)

mewa
  • 1,532
  • 1
  • 12
  • 20