0

I am trying to combine and unite the sequence of bytes from an int and a short

when debugging and reading the memory it's aligned like this [FF FF FF FF 00 00 00 00]

shouldn't it looked like this [FF FF FF FF FF FF 00 00] since i am using union?

   union uniteByte{
        
        unsigned int blockOne;
        unsigned short blockTwo;
    };
    
    union uniteByte testing;
    
    testing.blockOne =0xffffffff; //4294967295
    testing.blockTwo = 0xffff; //65535
    

    printf("%zu\n",sizeof(testing)); // size is 4 why? shouldn't it be 6?
    printf("%u\n",testing.blockOne); // 4294967295
    printf("%u\n",testing.blockTwo); // 65535
    printf("%p",&testing); //0x7ffeefbff4e0 [FF FF FF FF 00 00 00 00]
    printf("%p",&testing.blockOne); //0x7ffeefbff4e0 <-- the address is the same as in blockTwo
    printf("%p",&testing.blockTwo); //0x7ffeefbff4e0 <-- the address is the same as in blockOne
    
dn70a
  • 73
  • 2
  • 8
  • You're getting UB because `%x` expects an unsigned int, not an address. Addresses must be printed with `%p`. Besides `unsigned short` must be printed with `%d` because it'll be promoted to int, unless `sizeof(short) == sizeof(int)` – phuclv Jan 22 '22 at 15:17
  • Reading a different union member than the last one you wrote is implementation-dependent. – Barmar Jan 22 '22 at 15:18
  • @ phuclv alright gona make that change thanks – dn70a Jan 22 '22 at 15:19
  • @Barmar Type-punning via a union is fine in **C**, IIRC. It's UB in C++. – Adrian Mole Jan 22 '22 at 15:21
  • @AdrianMole I said implementation-dependent, not UB. – Barmar Jan 22 '22 at 15:22
  • The result will depend on things like endianness. – Barmar Jan 22 '22 at 15:22
  • @dn70a Not sure you are seeing the point of a union: the two members occupy the same memory, so why would you expect otherwise? – Adrian Mole Jan 22 '22 at 15:30
  • @AdrianMole When i read the memory it looks like `[FF FF FF FF 00 00 00 00]` <-- whouldn't it be `[FF FF FF FF FF FF 00 00]` also when printing the sizeof(testing) it showing to be 4 bytes instead of 6 – dn70a Jan 22 '22 at 15:32
  • Change your `union` to a `struct` to see the behaviour you seem to be expecting. Maybe this will help: [Difference between a Structure and a Union](https://stackoverflow.com/q/346536/10871073) – Adrian Mole Jan 22 '22 at 15:33
  • 1
    @AdrianMole the problem with the struct is that it uses empty bytes to align as for a integer alignment location. so if we reverse the position of blockOne and and blockTwo it would look like this `[FF FF 00 00 FF FF FF FF]` – dn70a Jan 22 '22 at 15:39
  • Why are you printing 8 bytes of memory when the union only uses 4 bytes? – Barmar Jan 22 '22 at 15:51
  • 1
    You might be able to get what you want using a packed structure. – Barmar Jan 22 '22 at 15:53
  • @Barmar i should accept your comment as an answer `__attribute__((packed))` changing union to packed structure did it – dn70a Jan 22 '22 at 16:01

1 Answers1

1

The purpose of a union is to use overlapping memory for each member, so the size is the size of the largest member, plus padding if necessary.

If you want the members to be independent, you have to use a struct. To get rid of the padding between members and at the end, use __attribute__((packed)).

Note that this will often have performance implications. CPU operations for moving numbers between memory and registers generally have alignment requirements, which is why structures normally have padding. When you pack the structure, the data has to be moved byte-by-byte instead of using single instructions for the full size of the number. So it should only be done when memory efficiency is at a premium and you need this time-space tradeoff.

Barmar
  • 741,623
  • 53
  • 500
  • 612