0

I want to write my data into an array that is part of a union. Even though I can write to every element in the array, when I retrieve the value from the array in the union, I only get the value from the first element.

When I do the same thing but do not use an array, it works as expected.

Can anyone explain to me, why it does not work using an array or point out my error?

Thank you.

#include <stdio.h>
#include <stdint.h>
#include <string.h>

int main() {
    struct struct_v1 {
        unsigned a: 2;
        signed b: 3;
    };

    union {
        struct struct_v1 data[3];
        uint16_t data_uint;
    } union_v1;

    memset(&union_v1.data_uint, 0, sizeof(union_v1.data_uint));
    for (int i = 0; i < 3; ++i) {
        union_v1.data[i].a = 1;
        union_v1.data[i].b = -i;
    }

    struct struct_v2 {
        unsigned a_0: 2;
        signed b_0: 3;
        unsigned a_1: 2;
        signed b_1: 3;
        unsigned a_2: 2;
        signed b_2: 3;
    };

    union {
        struct struct_v2 data;
        uint16_t data_uint;
    } union_v2;

    memset(&union_v2.data_uint, 0, sizeof(union_v2.data_uint));
    union_v2.data.a_0 = 1;
    union_v2.data.b_0 = 0;
    union_v2.data.a_1 = 1;
    union_v2.data.b_1 = -1;
    union_v2.data.a_2 = 1;
    union_v2.data.b_2 = -2;


    printf("union_v1 = 0x%04X\n", union_v1.data_uint);  // 0x0001
    printf("union_v2 = 0x%04X\n", union_v2.data_uint);  // 0x67A1
    return 0;
}

https://coliru.stacked-crooked.com/a/0d93b4f6779e40e2

timrau
  • 22,578
  • 4
  • 51
  • 64
HennyKo
  • 712
  • 1
  • 8
  • 19
  • 4
    Because the size of a structure must be in whole bytes. In this case, `struct_v1` gets padded to 4 bytes. – Detheroc Nov 12 '21 at 21:55
  • 1
    Because of padding and alignment. You can print out the sizes of the structs to see that `union_v1` is 12 bytes and `union_v2` is only 4 because all of the 6 bit fields fit into a single `int`. – Cheatah Nov 12 '21 at 22:03
  • Thank you for the explanation. What a shame, I would have loved to use an array rather than having to type out every element of `struct_v1` multiple times. – HennyKo Nov 12 '21 at 22:20
  • Shouldn't `struct struct_v1 {unsigned a: 2; signed b: 3;} __attribute__((packed));` be a workaround? Now both unions are of size 4bytes. But I get `0x1D01` for `union_v1`. – HennyKo Nov 12 '21 at 22:27
  • If one of you two makes an answer out of their comment, I will accept it. I will ask a new question regarding "packed". – HennyKo Nov 12 '21 at 22:50
  • 1
    A struct must have a minimal size of one byte https://stackoverflow.com/a/29684648/9309705, that's why packing the struct does not return the desired result. – HennyKo Nov 12 '21 at 23:14

0 Answers0