1

Recently learned about unions in c++ and I come up with this in order to handle multiple flags represented by a single uint64_t,etc

union myflags_t
{
  uint64_t var;
  std::bitset<64> bits;

  myflags_t() { }
};

The alternative way I was using before was bit operations, specifically setting a bit and changing the nth bit to x.

Instead I can use

myflags_t flags;
flags.var = 0;
flags.bits[nth bit] = ...

My question is Which is faster the union or bit operations?

Also if it is faster to use the union why haven't I come across this before?

Edit: Removed memset (misunderstood and did not need it) The reason I'm using union is because later in the code I need to pass the variable as uint64_t Edit 2: Read over comments and I'm convinced that I'm using union wrong. The code creates undefined behaviour since unions are not meant for type punning. Going to close the question.

Community
  • 1
  • 1
Sahar Rabinoviz
  • 1,939
  • 2
  • 17
  • 28
  • 3
    "if it is faster to use the union why haven't I come across this before?" - because it's relying on undefined behaviour. – Mike Seymour May 28 '15 at 16:57
  • @LightnessRacesinOrbit What should I be using instead of memset? – Sahar Rabinoviz May 28 '15 at 17:04
  • If you're going to use the std, use the std. In this case, bits.reset() will reset everything stored in bits to 0. Adding the union in this example only makes things less clear. Not an answer to your question, but I wasn't trying for one. – Aumnayan May 28 '15 at 17:22
  • @DisplayName101: At the very least, switch to `std::fill`. In industry I've seen terrible bugs go undiagnosed for years when an array was swapped for a map (yeah) and the lack of useful type safety on `memset` meant the entire container was being silently ruined (causing UB). – Lightness Races in Orbit May 28 '15 at 17:25
  • @Aumnayan the reason I'm using union is because I have to send to send it as a uint64_t later, not because it allows to me set it to 0 quickly. – Sahar Rabinoviz May 28 '15 at 17:27
  • 1
    @DisplayName101: You're abusing `union` to perform invalid type punning. This is not what `union` is for. It's a common misconception. – Lightness Races in Orbit May 28 '15 at 17:29
  • @DisplayName101: look up bitfields then. This isn't a portable solution as it's behavior is determined by the compiler and not a standard, but if that's not a problem for you it will provide the clean interface you're looking for. – Aumnayan May 28 '15 at 17:31
  • @LightnessRacesinOrbit I read over [union](http://stackoverflow.com/a/2313676/3024116) and I understand that they were created for saving memory, but from what I understood from the link since C99 using union for type punning is ok – Sahar Rabinoviz May 28 '15 at 17:34
  • @Aumnayan: It's UB so the behaviour can vary on the same compiler between compilation runs or even between execution runs. _Anything_ can happen. It'll never not be a problem for you. – Lightness Races in Orbit May 28 '15 at 17:34
  • @DisplayName101: Either the link is wrong or you understood it incorrectly (though there is a subset of cases in which it's okay). And C++ is not C99. – Lightness Races in Orbit May 28 '15 at 17:34
  • 1
    @DisplayName101 As others have said, `union` is not designed to flip bits between types. It is designed to save space when you only need one of the types. If you need to use a `uint32_t` at some point, you should probably just use a `uint32_t` from the beginning and stick with it. You could also just use a `bitset` and convert it to a `uint32_t` later. – Apples May 28 '15 at 17:36
  • I'm voting to close this question as off-topic because .... – Sahar Rabinoviz May 28 '15 at 17:47
  • @Lightness Races in Orbit : That not an all inclusive answer, thought it might be accurate for your working environment. For example: http://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#Bit-Fields defines how bit fields are used in GNU gcc/g++. In that environment bitfields operate in a very precise way. – Aumnayan May 28 '15 at 17:54
  • Just use `std::bitset`. It has `to_ulong()` and `to_ullong()`. – T.C. May 28 '15 at 18:03
  • @Aumnayan: We're talking about how `union` works, not how bitfields work. – Lightness Races in Orbit May 28 '15 at 18:04

1 Answers1

0

If you want to flip the nth bit you can do this.

#include <iostream>
#include <bitset>
#include <cstdint>

int main( void )
{
  uint64_t u64 = 1024;
  std::bitset <64> b64;

  b64 = u64;
  b64.flip(0);

  u64 = b64.to_ulong();

  std::cout << u64 << "\n";

  return 0;
}
Moises Rojo
  • 371
  • 2
  • 14