🧾 What is a Union?
A Union in C is a user-defined data type (just like a struct) that allows storing different types of data in the same memory location.
Unlike structures, in unions:
All members share the same memory space.
Only one member can contain a meaningful value at a time.
<div class="infographic-cunion2">
<style>
.infographic-cunion2 {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--code-bg: #1e1e2e;
--code-text: #d4d4e0;
--syn-keyword: #c586c0;
--syn-comment: #6a9955;
}
.infographic-cunion2[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--code-bg: #0d0d14;
--code-text: #d4d4e0;
}
.infographic-cunion2 {
box-sizing: border-box;
max-width: 880px;
margin: 0 auto;
background: var(--paper);
color: var(--ink);
font-family: 'Inter', -apple-system, sans-serif;
padding: 0 clamp(1rem, 4vw, 2.25rem) 1.25rem;
}
.infographic-cunion2 *, .infographic-cunion2 *::before, .infographic-cunion2 *::after {
box-sizing: border-box;
}
.infographic-cunion2 h1 {
font-family: 'Fraunces', Georgia, serif;
font-weight: 600;
font-size: clamp(1.3rem, 3.5vw, 1.7rem);
margin: 1.25rem 0 0.2rem;
text-align: center;
}
.infographic-cunion2 .subhead { color: var(--ink-soft); font-size: 0.85rem; margin-bottom: 1.2rem; text-align: center; }
.infographic-cunion2 .code-panel {
background: var(--code-bg);
color: var(--code-text);
border-radius: 8px;
padding: 0.65rem 0.9rem;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.82rem;
line-height: 1.6;
margin-bottom: 1.1rem;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.infographic-cunion2 .code-panel .code-line { display: block; white-space: pre; }
.infographic-cunion2 .syn-keyword { color: var(--syn-keyword); }
.infographic-cunion2 .syn-comment { color: var(--syn-comment); }
.infographic-cunion2 .mem-row { display: flex; justify-content: center; gap: 0.4rem; margin-bottom: 0.3rem; }
.infographic-cunion2 .mem-cell { text-align: center; }
.infographic-cunion2 .mem-name {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.72rem;
color: var(--ink-soft);
margin-bottom: 0.3rem;
}
.infographic-cunion2 .mem-box {
height: 3rem;
width: 9rem;
border: 2px solid var(--accent);
background: var(--accent-soft);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
padding: 0 0.3rem;
}
.infographic-cunion2 .mem-box input {
all: unset;
width: 100%;
text-align: center;
font-family: 'IBM Plex Mono', monospace;
font-size: 0.95rem;
font-weight: 700;
color: var(--accent);
}
.infographic-cunion2 .mem-bytes { font-family: 'IBM Plex Mono', monospace; font-size: 0.66rem; color: var(--ink-soft); margin-top: 0.25rem; }
.infographic-cunion2 .facts { text-align: center; font-family: 'IBM Plex Mono', monospace; font-size: 0.8rem; color: var(--ink-soft); margin: 0.9rem 0 1.1rem; }
.infographic-cunion2 .facts strong { color: var(--ink); }
.infographic-cunion2 .access-panel {
background: var(--paper-alt);
border-radius: 8px;
padding: 0.8rem 1rem;
}
.infographic-cunion2 .access-line {
font-family: 'IBM Plex Mono', monospace;
font-size: 0.82rem;
display: flex;
justify-content: space-between;
gap: 0.5rem;
padding: 0.2rem 0;
}
.infographic-cunion2 .access-line span:first-child { color: var(--ink-soft); }
.infographic-cunion2 .access-line strong { color: var(--accent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 12rem; }
.infographic-cunion2 .takeaway {
font-size: 0.82rem; color: var(--ink-soft);
margin-top: 1.3rem; border-top: 1px solid var(--line); padding-top: 0.9rem;
}
.infographic-cunion2 .takeaway strong { color: var(--ink); }
</style>
<div class="code-panel">
<span class="code-line"><span class="syn-keyword">union</span> Data {</span>
<span class="code-line"> <span class="syn-keyword">int</span> i; <span class="syn-comment">// 4 bytes</span></span>
<span class="code-line"> <span class="syn-keyword">float</span> f; <span class="syn-comment">// 4 bytes</span></span>
<span class="code-line"> <span class="syn-keyword">char</span> str[20]; <span class="syn-comment">// 20 bytes</span></span>
<span class="code-line">};</span>
</div>
<div class="mem-row">
<div class="mem-cell">
<div class="mem-name">i</div>
<div class="mem-box"><input type="number" id="cu-i" value="65"></div>
<div class="mem-bytes">4 bytes</div>
</div>
</div>
<p class="facts">sizeof(union Data) = <strong>20 bytes</strong> <span style="opacity:0.7;">(the largest member, not the sum)</span></p>
<div class="access-panel">
<div class="access-line"><span>d.i</span><strong id="acc-i">65</strong></div>
<div class="access-line"><span>d.f</span><strong id="acc-f">—</strong></div>
<div class="access-line"><span>d.str</span><strong id="acc-s">—</strong></div>
</div>
<p class="takeaway"><strong>Edit the box above</strong> — d.i, d.f, and d.str all read the exact same bytes, just interpreted as three different types.</p>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-cunion2')
|| document.querySelector('.infographic-cunion2');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
function $(sel) { return wrapper.querySelector(sel); }
const iInput = $('#cu-i');
const accI = $('#acc-i'), accF = $('#acc-f'), accS = $('#acc-s');
const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);
const bytes = new Uint8Array(buffer);
function floatStr(v) {
if (Number.isNaN(v)) return 'NaN';
if (!Number.isFinite(v)) return v > 0 ? 'Infinity' : '-Infinity';
if (Math.abs(v) > 1e12 || (Math.abs(v) < 1e-6 && v !== 0)) return v.toExponential(4);
return String(Math.round(v * 1e6) / 1e6);
}
function strFromBytes() {
let out = '';
for (let i = 0; i < 4; i++) {
const b = bytes[i];
if (b === 0) break;
out += (b >= 32 && b <= 126) ? String.fromCharCode(b) : '\u00b7';
}
return out.length ? '"' + out + '"' : '""';
}
function update() {
const v = Math.trunc(Number(iInput.value)) || 0;
view.setInt32(0, v, true);
accI.textContent = v;
accF.textContent = floatStr(view.getFloat32(0, true));
accS.textContent = strFromBytes();
}
iInput.addEventListener('input', update);
update();
})();
</script>📦 Memory Behavior of Union vs Structure
Let’s consider this example:
union Data {
int i; // 4 bytes
float f; // 4 bytes
char str[20]; // 20 bytes
};Member | Size |
|---|---|
| 4 bytes |
| 4 bytes |
| 20 bytes |
✅ Total Memory Allocated:
Structure = 4 + 4 + 20 = 28 bytes (plus possible padding)
Union = 20 bytes (only the size of the largest member)
Because in a union, all members occupy the same location, so only one value is stored at a time.
🔤 Syntax of a Union
union UnionName {
dataType member1;
dataType member2;
...
};✅ Example:
union Data {
int i;
float f;
char str[20];
};📥 Accessing Union Members
#include <stdio.h>
#include <string.h>
union Data {
int i;
float f;
char str[20];
};
int main() {
union Data d;
d.i = 10;
printf("d.i = %d\\n", d.i);
d.f = 220.5; // overwrites 'i'
printf("d.f = %.1f\\n", d.f);
strcpy(d.str, "Hello"); // overwrites 'f'
printf("d.str = %s\\n", d.str);
return 0;
}⚠️ Important:
After writing to
d.f, the previous valued.iis no longer valid.Only the last written member can be safely accessed.
🧠 How Does Union Actually Work?
Think of union like a container that changes its shape depending on what you put in:
If you put in an
int, it becomes an int holder.If you later put in a
float, it now becomes a float holder — and previous int is lost.
Why? Because all members start at the same memory address.
🏁 Use Cases of Unions in C
When you need to store one value at a time from multiple options, union helps save space.
📦 Example:
union PaymentMethod {
int cardNumber;
char upiID[20];
long walletNumber;
};Instead of using a structure (which would take memory for all 3), union saves memory.
Used when the type of data is not fixed — common in parsing, network protocols, or data serialization.
struct Variant {
int type; // 1: int, 2: float, 3: char*
union {
int i;
float f;
char str[20];
} data;
};You check the type field to decide how to interpret data.
In low-level programming (e.g., microcontrollers), unions are used to map one memory location to multiple meanings.
Example:
union Register {
unsigned int all_bits;
struct {
unsigned int flag1 : 1;
unsigned int flag2 : 1;
...
} bits;
};This allows treating memory as a whole or bit-by-bit.
When dealing with binary data formats, sometimes you don’t know what type will be stored. Unions help with interpreting that memory correctly.
❗ Important Things to Keep in Mind
🔍 Concept | ✅ Union |
|---|---|
Memory | Only max-sized member |
Simultaneous access | ❌ Not safe — only 1 member at a time |
Last written wins | ✅ Always |
Use with structures | ✅ Common pattern (tag + union) |
Flexible | ✅ Yes |
Safe access | ⚠️ Only access what you last assigned |
🔄 Union vs Structure — Summary Table
Feature |
|
|
|---|---|---|
Memory | Sum of all members | Size of largest member |
Access | All members accessible at once | Only one at a time |
Use Case | Store related data together | Store one value out of many types |
Safety | Safer | Risky if misused |
Efficiency | Less memory-efficient | More efficient (memory-wise) |