3 min read
Type Punning in C++: A Simple Guide

There are a few explanations of type punning you’ll find in various places: on Stack Overflow here, for example, and here. These are perfectly good resources, but they slightly gloss over what is actually happening and why.

What is type punning?

Type punning is when you treat a value of one type as if it were a value of another type without converting it — just reinterpreting the raw bits.

Think of it like this:

“Hey compiler, I know this is a float, but I want to pretend it’s an int and just look at the same memory as if it were an int.”

This is mostly done in systems and embedded programming, where you want to peek under the hood at the binary layout.

Example: Bit Representation of a Float

float pi = 3.14f;

This float is stored in memory as a 32-bit pattern (binary data). You want to read those 32 bits as an integer — not convert 3.14 to the integer 3, but literally see what the binary pattern looks like.

Incorrect Approach: static_cast

uint32_t first = static_cast<uint32_t>(pi);
  • This is valid C++
  • But it’s not what you want

Why? static_cast converts the value, not the bit pattern. It converts 3.14 → 3.

Dangerous Approach: reinterpret_cast (the “clever” hack)

uint32_t second = *reinterpret_cast<uint32_t*>(&pi);

This looks like it works:

  1. Take the address of the float &pi
  2. Cast the pointer to uint32_t*
  3. Dereference that to get the int value

However, you just told the compiler to treat float memory as int memory, and this is undefined behavior in C++.

Why Is This Undefined Behavior?

Even though it works on many compilers and platforms (especially in embedded systems), the C++ standard says:

You are not allowed to access an object through a pointer of an incompatible type.

This is called the strict aliasing rule. It allows the compiler to assume that float* and uint32_t* point to different objects, so it can optimize aggressively.

In uint32_t second = *reinterpret_cast<uint32_t*>(&pi);, you’re violating that rule.

So what might happen?

  • It might work
  • It might get optimized away
  • It might crash
  • It might give garbage

Because it’s undefined behavior, anything can happen.

The Correct Way to Do Type Punning in C++

Use std::memcpy — this is defined and safe:

float pi = 3.14f;
uint32_t bits;
std::memcpy(&bits, &pi, sizeof(bits));

This says:

“Copy the bytes from the float into an integer safely.”

This is guaranteed to do what you want and is allowed by the C++ standard.