0
// unions.cpp
// Defines and uses a union.
// ---------------------------------------------------
#include <iostream>
using namespace std;
union WordByte
{
    private:
       unsigned short w;

       unsigned char b[2];                         // an array member of size 2? 

    public:

       unsigned short& word()     { return w; }    // public methods have access to the private members
       unsigned char& lowByte() { return b[0]; }
       unsigned char& highByte(){ return b[1]; }
};



int main()
{
    WordByte wb;                                   // create an instance of WordByte with name wb
    wb.word() = 256;                               // access the public members .word()
    cout << "\nWord:" << (int)wb.word();           // access the public members .word(), transfer the returned value to int type
    cout << "\nLow-byte: " << (int)wb.lowByte()    // access the public members .lowByte(), explicit casting
         << "\nHigh-byte: " << (int)wb.highByte()  // access the public members .highByte(), explicit casting
         << endl;
    return 0;
}

Hi, the above code is excepted from the book a complete guide to c++. When I run it, the following is the output:

~$ g++ units.cpp
~$ ./a.out

Word:256
Low-byte: 0
High-byte: 1

I understand why the output 256. But why 0 and 1 in the output?

kkxx
  • 571
  • 1
  • 5
  • 16
  • 6
    Accessing an inactive union field is undefined behavior. That said, 256 is `00000001 00000000` in binary, so I'm not sure what suprises you. Do you know what a `union` is? – HolyBlackCat Nov 18 '19 at 10:14
  • 256 = 0x0100 => high byte is 0x01, low byte is 0x00 – phuclv Nov 18 '19 at 10:16
  • 256 does not surprise me. I was a bit surprised by 0 and 1 in the output. Do you mean that it is like random/arbitrary behavior to access b[0] and b[1]? – kkxx Nov 18 '19 at 10:16
  • 3
    What values did you expect to see and why? – rustyx Nov 18 '19 at 10:21
  • @kkxx Undefined behavior means the program can do anything, including working properly, or crashing randomly. See: [this](https://en.cppreference.com/w/cpp/language/ub) and [this](https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior). This case of UB is relatively tame though (e.g. at least GCC always allows it). – HolyBlackCat Nov 18 '19 at 10:26
  • Reading uninitialised variable from stack can give garbage value. In your case that 2byte is set to decimal 256 equivalent to 0x0100. And based on endieness Upper and lower byte is displayed. But with same garbage value different HW can show different result. – TruthSeeker Nov 18 '19 at 10:32

2 Answers2

0

In C++, since there is currently no active member of the union, the behaviour on reading any of the members is undefined.

The type of the union member is not relevant. (An uninitialised automatic unsigned char is readable; it's an important exception to the general rule that reading uninitialised variables is undefined.)

(Note that in C, the behaviour of reading back the unsigned char array member would not be undefined - this is because C permits the union type pun; C++ doesn't.)

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
-1

A union is a datatype whereby all elements defined within it inhabit the same memory address and is allocated the memory required to implement its largest element.

In your case you have an unsigned short (16 bits) in a union with a 2 char array (also 16 bits).

It just so happens that on the processor that you are using the arrangement of most significant to least significant byte for the unsigned short is such that its most significant byte is at the same memory location as b[1] and its least significant byte is at the memory location for b[0].

Occasionally you see unions used incorrectly in this manner to quickly convert data types to arrays of bytes and vice versa, but be cautious as whether it works or not is processor dependent.

ChrisBD
  • 9,104
  • 3
  • 22
  • 35