0

I am using c programming in PIC18F87K90 microcontroller. I am having a problem about creating a structure variable (with union within it) to have an easier access to multiple flags (most are 1-bit flags, but some are 2-bit or 3-bits).

The code below works well. I used simulator to check the address bytes of each member. The members of the structure inside the union are grouped in the same address byte, which I expect since the members have a total of 8-bits which should fit in 1-byte. I also check the addresses of: eeprom_flag.byte0, eeprom_flag.reset_time_byte... etc and they are in same address due to union usage. My problem is that I wanted to have two possible names for one of the 1-bit flag, which is eeprom_flag.output_time_bit. I wanted to have another name for it (but exactly same variable-bit, same address). I tried using union to do that (see commented lines below). However, doing that will break my code such that the members of the structure are no longer in same addresses. My goal to do addressing as seen in the uploaded image.

typedef struct
{
    //buffer index 0
    union
    {
        struct
        {
            uint8_t reset_time_bit:1;
//            union
//            {
                uint8_t output_time_bit:1;      //shared address
//                uint8_t output2_time_bit:1;
//            };
            uint8_t count_mode_bit:3;
            uint8_t input_mode_bit:1;
            uint8_t count_speed_bit:2;
        };
        uint8_t byte0;
        uint8_t reset_time_byte;
        uint8_t output_time_byte;
        uint8_t output2_time_byte;
        uint8_t count_mode_byte;
        uint8_t input_mode_byte;
        uint8_t count_speed_byte;
    };
} eeprom_flag_t;
extern volatile eeprom_flag_t   eeprom_flag;

Expected mapping

user139731
  • 129
  • 5
  • The smallest size for a union is one byte. You can't achieve what you're after. There's some sense to using a union of the structure containing the bit fields and one of the other names. There is very little obvious benefit to having 7 (instead of just 1) names for the 8-bit value. – Jonathan Leffler Aug 28 '20 at 04:30
  • 1
    Maybe: `#define output2_time_bit output_time_bit` – Mike Aug 28 '20 at 04:45
  • Thx for suggestions. Regarding not using #define, #ifdef, #endif, the decision whether to use output2_time_bit or output_time_bit will be made after the initialization of my microcontroller, so it's technically at run time, although just at initialization. – user139731 Aug 28 '20 at 05:12

2 Answers2

0

Although I do not understand why you would want that, the following might do what you want.

The idea is that you define 2 bit-fields (struct) which overlap (union) in a way that pleases you.

union
{
    struct { uint8_t output_time_bit:1;} ;
    struct { uint8_t output2_time_bit:1;} ;
}
virolino
  • 2,073
  • 5
  • 21
0

In theory, what you want may be possible but in practice, no vendor has ever written a compiler that will do that. Generally unions are aligned to byte boundaries. On some compilers, they are aligned to 2, 4, 8 or 16 byte boundaries.

You'd have to re-declare the entire structure to achieve what you want. There is no need to put a union in a struct - the union can be used directly in a typedef). Also if you don't name the internal structs, you may not be able to look at the values in a debugger. Debuggers are temperamental on this - sometimes you can and sometimes you can't.

typedef union
{
    struct
    {
        uint8_t reset_time_bit:1;
        uint8_t output_time_bit:1;      //shared address
        uint8_t count_mode_bit:3;
        uint8_t input_mode_bit:1;
        uint8_t count_speed_bit:2;
    } bits1;
    struct
    {
        uint8_t reset_time_bit:1;
        uint8_t output2_time_bit:1;
        uint8_t count_mode_bit:3;
        uint8_t input_mode_bit:1;
        uint8_t count_speed_bit:2;
    } bits2;
    uint8_t byte0;
    ...
} eeprom_flag_t;

Alternatively, as @Mike suggested, just have one structure and #define the bitfield of the other one.

Generally the compiler will generate less code if | and & are used. Using bits generates a lot of shifting left and right in addition to the or-ing and and-ing. You can get very confused very quickly when looking at the generated code.

cup
  • 7,589
  • 4
  • 19
  • 42