5

Can somebody clear me out why would I use union and with what purpose the same address for the cin'ed variable and bit field (task from the Schildts C++ book)? In other words why would I use union for :

char ch; struct byte bit;

// Display the ASCII code in binary for characters.

#include <iostream>
#include <conio.h>
using namespace std;

// a bit field that will be decoded
struct byte {
  unsigned a : 1;
  unsigned b : 1;
  unsigned c : 1;
  unsigned d : 1;
  unsigned e : 1;
  unsigned f : 1;
  unsigned g : 1;
  unsigned h : 1;
};

union bits {
  char ch;
  struct byte bit;
} ascii ;

void disp_bits(bits b);

int main()
{
  do {
    cin >> ascii.ch;
    cout << ": ";
    disp_bits(ascii);
  } while(ascii.ch!='q'); // quit if q typed

  return 0;
}

// Display the bit pattern for each character.
void disp_bits(bits b)
{
  if(b.bit.h) cout << "1 ";
    else cout << "0 ";
  if(b.bit.g) cout << "1 ";
    else cout << "0 ";
  if(b.bit.f) cout << "1 ";
    else cout << "0 ";
  if(b.bit.e) cout << "1 ";
    else cout << "0 ";
  if(b.bit.d) cout << "1 ";
    else cout << "0 ";
  if(b.bit.c) cout << "1 ";
    else cout << "0 ";
  if(b.bit.b) cout << "1 ";
    else cout << "0 ";
  if(b.bit.a) cout << "1 ";
    else cout << "0 ";
  cout << "\n";
}
highlevelcoder
  • 345
  • 1
  • 3
  • 10
  • 6
    "task from the Schildts C++ book" - this is where you are going wrong - or have we been through this? And the code arguably exhibits undefined behaviour. –  Jun 17 '10 at 22:03
  • 1
    You might consider getting a new book: [The Definitive C++ Book Guide and List](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) has a few very good introductory books. – James McNellis Jun 17 '10 at 22:14
  • 1
    Notice how conio.h has snuck in there too. –  Jun 17 '10 at 22:22

4 Answers4

7

As a union, both ch and bit have an overlapped (shared) memory location. Store a character in it as ch and then reading bit produces the corresponding bit values for the character.

Mark Wilkins
  • 40,729
  • 5
  • 57
  • 110
  • 3
    C++ says that doing this is undefined. I'm not clear if it is still undefined if you use a copy of the union to perform the second operation. –  Jun 17 '10 at 22:06
  • @Neil: I'm probably just way behind the times (and am probably missing something besides), but the Stroustrup book I have says that they will occupy the same memory (assuming they are the same size). I'm not saying this is a good use of the union, however. What part of the operation is undefined? – Mark Wilkins Jun 17 '10 at 22:15
  • The C++ standard says that a union instance can only hold one of the members it is a union of. Trying to use the same instance to access one of the other members is undefined. This does however "work" on all platforms I'm aware of, but that's what the standard says. Basically, unions are intended to be something like variant records, not ways of mapping individual bits between types. –  Jun 17 '10 at 22:19
  • It is undefined according to the standard, but major compilers guarantees that the trick of writing to one union member and reading from another will work, because it's so commonly done. – jalf Jun 17 '10 at 22:47
  • @jalf - using `static_assert(sizeof(bits) == 1, "assumption broken");` removes any doubt; if this holds true and compiles, the standard says this behavior is well defined (in an induction proof kinda way). static assert is amazing for ease of mind in situations like this. – Anne Quinn Aug 30 '21 at 08:52
5

The real answer is - you wouldn't. Using bitfields in unions (or at all) like this is inherently unportable and may be undefined. If you need to fiddle with bits, you are much better off using the C++ bitwise operators.

1

Because the exercise demonstrates breaking up a value into bits using a bitfield and a union.

Assuming you know what a union is, if you were extracting something less repetitive from a binary value then you might want use it for clarity instead of making say two 24 bit integers from 48 chars out of shifts and masks.

But for the example in the task, shifts and masks would be much cleaner code, so you would probably not use a union for this task.

void disp_bits(unsigned b)
{ // not tested
    for ( int shift = 7; shift >= 0;  --shift )
        cout <<  ( ( b >> shift ) & 1 ) << ' ';

    cout << "\n";
}
Pete Kirkham
  • 48,893
  • 5
  • 92
  • 171
-6

Unions are used in network protocols. They can also be handy to fake out polymorphism in C. Generally they are a special use case.

In this example, it is sort of a dummy example to show you a little code.

Paul Nathan
  • 39,638
  • 28
  • 112
  • 212