13

I use the following union to simplify byte, nibble and bit operations:

union Byte
{
  struct {
    unsigned int bit_0: 1;
    unsigned int bit_1: 1;
    unsigned int bit_2: 1;
    unsigned int bit_3: 1;
    unsigned int bit_4: 1;
    unsigned int bit_5: 1;
    unsigned int bit_6: 1;
    unsigned int bit_7: 1;
  };

  struct {
    unsigned int nibble_0: 4;
    unsigned int nibble_1: 4;
  };

  unsigned char byte;
};

It works nice, but it also generates this warning:

warning: ISO C++ prohibits anonymous structs [-pedantic]

Ok, nice to know. But... how to get this warning out of my g++ output? Is there a possibility to write something like this union without this issue?

tshepang
  • 12,111
  • 21
  • 91
  • 136
Dejwi
  • 4,393
  • 12
  • 45
  • 74
  • 2
    Why not simply name your struct? – Luchian Grigore Apr 24 '13 at 21:31
  • 4
    You won't be able to do what you're trying to do within the realms of valid C++. It might work, but it will be undefined behaviour. – Kerrek SB Apr 24 '13 at 21:32
  • I can name it - for example struct nibbles and make it a field of a union. But then I will have to access it Byte.nibbles.nibble_0. It won't be so nice to use ;). – Dejwi Apr 24 '13 at 21:35
  • 1
    Or, `Byte.nibble.n0` or `Byte.nibble._<0>()` or `Byte.nibble._[0]` or `get<0>(Byte.nibble)` or because you can DRY and drop the repeated `nibble` inside the `struct` named `nibble` when accessing it, and maybe gussy it up in some trade dress. – Yakk - Adam Nevraumont Apr 24 '13 at 21:44
  • What @KerrekSB said. Gcc will, for example, invert the field order with endianness, making bit 7 appear as bit 0. You might be better off using `bool bit(unsigned int n) const { return byte & (1 << n); }` – Simon Richter May 13 '14 at 09:03

1 Answers1

12

The gcc compiler option -fms-extensions will allow non-standard anonymous structs without warning.

(That option enables what it considers "Microsoft extensions")

You can also achieve the same effect in valid C++ using this convention.

union Byte
{
  struct bits_type {
    unsigned int _0: 1;
    unsigned int _1: 1;
    unsigned int _2: 1;
    unsigned int _3: 1;
    unsigned int _4: 1;
    unsigned int _5: 1;
    unsigned int _6: 1;
    unsigned int _7: 1;
  } bit;
  struct nibbles_type {
    unsigned int _0: 4;
    unsigned int _1: 4;
  } nibble;
  unsigned char byte;
};

With this, your non-standard byte.nibble_0 becomes the legal byte.nibble._0

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
  • 3
    You are correct about the leading underscore. Names in the global namespace that begin with an underscore are reserved to the implementation. Names starting with an underscore followed by an uppercase letter or that contain double underscores are also reserved to the implementation. - See 17.6.4.3.2 (C++11) – Captain Obvlious Apr 24 '13 at 22:05