in Code

Accessing and manipulating a 32bit integer as a byte array in C++ using unions

I don’t think I’ve ever used union for anything, but today I came across a very interesting use case to avoid bit-shifting tricks when dealing with data embedded in numbers.

What’s a union?

Microsoft defines it this way

union is a user-defined type in which all members share the same memory location. This definition means that at any given time, a union can contain no more than one object from its list of members. It also means that no matter how many members a union has, it always uses only enough memory to store the largest member.

Example:

union IntChar {
    unsigned int i;
    char c;
};

IntChar foo;
foo.i = 65; // 'A' in ASCII                                                                                                                                            
printf("i: %d, c: %c\n", foo.i, foo.c);

// i: 65. c: A
Represent an integer as a char, or char as int

We can also do the same with an anonymous union, and directly use the variables, which will change each other’s values



union {
  unsigned int i;
  char c:
}
c='A';
printf("i: %d, f: %c\n", i, c);
// i: 65, c: A


Let’s apply this feature to a 32 bit integer (4 bytes) and a 4 byte array

This I believe might come in handy if you need to use integers as arrays of 8 bit numbers because you can use the array ‘[]’ operator to access the individual bytes in the number without having to do bit shifting tricks (>>,<<,&,|) to extract them or manipulate them

#include <iostream>

int main() {
  union {
    unsigned int a; // 32 bit number, 4 bytes                                                                                                                            
    unsigned char aa[4]; // access a's bytes as an array                                                                                                                 
  };

  a = 0xaabbccdd;
  printf("a: 0x%x\n", a); //        a: 0xaabbccdd                                                                                                                        
                          // where: aa[3]=0xaa, a[2]=0xbb, a[1]=0xcc, a[0]=0xdd                                                                                          

  for (unsigned int i=0; i < 4; i++) {
    printf("a[%d]: 0x%x\n", i, (unsigned int) aa[i]);
  }

  aa[0]=0xff;
  printf("a: 0x%x\n", a);

  return 0;
}

 

Build and output:

$ g++ int_as_array.cpp && ./a.out
a: 0xaabbccdd
a[0]: 0xdd
a[1]: 0xcc
a[2]: 0xbb
a[3]: 0xaa
a: 0xaabbccff

DO NOT USE THIS TECHNIQUE IN PRODUCTION CODE:

Here’s a word about this trick from my very esteemed friend (and elite coder) Dave Nicponski

Write a Comment

Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.