summaryrefslogtreecommitdiff
path: root/devdocs/c/language%2Funion.html
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2024-04-07 13:41:34 -0500
committerCraig Jennings <c@cjennings.net>2024-04-07 13:41:34 -0500
commit754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 (patch)
treef1190704f78f04a2b0b4c977d20fe96a828377f1 /devdocs/c/language%2Funion.html
new repository
Diffstat (limited to 'devdocs/c/language%2Funion.html')
-rw-r--r--devdocs/c/language%2Funion.html80
1 files changed, 80 insertions, 0 deletions
diff --git a/devdocs/c/language%2Funion.html b/devdocs/c/language%2Funion.html
new file mode 100644
index 00000000..bd3b949b
--- /dev/null
+++ b/devdocs/c/language%2Funion.html
@@ -0,0 +1,80 @@
+ <h1 id="firstHeading" class="firstHeading">Union declaration</h1> <p>A union is a type consisting of a sequence of members whose storage overlaps (as opposed to struct, which is a type consisting of a sequence of members whose storage is allocated in an ordered sequence). The value of at most one of the members can be stored in a union at any one time.</p>
+<p>The <a href="declarations" title="c/language/declarations">type specifier</a> for a union is identical to the <a href="struct" title="c/language/struct"><code>struct</code></a> type specifier except for the keyword used:</p>
+<h3 id="Syntax"> Syntax</h3> <table class="t-sdsc-begin"> <tr class="t-sdsc"> <td> <code>union</code> <span class="t-spar">attr-spec-seq</span> <span class="t-mark">(optional)</span> <span class="t-spar">name</span> <span class="t-mark">(optional)</span> <code>{</code> <span class="t-spar">struct-declaration-list</span> <code>}</code> </td> <td> (1) </td> <td class="t-sdsc-nopad"> </td>
+</tr> <tr class="t-sdsc"> <td> <code>union</code> <span class="t-spar">attr-spec-seq</span> <span class="t-mark">(optional)</span> <span class="t-spar">name</span> </td> <td> (2) </td> <td class="t-sdsc-nopad"> </td>
+</tr>
+</table> <table class="t-par-begin"> <tr class="t-par"> <td> <span class="t-spar">name</span> </td> <td> - </td> <td> the name of the union that's being defined </td>
+</tr> <tr class="t-par"> <td> <span class="t-spar">struct-declaration-list</span> </td> <td> - </td> <td> any number of variable declarations, <a href="bit_field" title="c/language/bit field">bit-field</a> declarations, and static assert declarations. Members of incomplete type and members of function type are not allowed. </td>
+</tr> <tr class="t-par"> <td> <span class="t-spar">attr-spec-seq</span> </td> <td> - </td> <td> <span class="t-mark-rev t-since-c23">(C23)</span>optional list of <a href="attributes" title="c/language/attributes">attributes</a>, applied to the union type, not allowed for <span class="t-v">(2)</span> if such form is not followed by a <code>;</code> (i.e. not a forward declaration). </td>
+</tr>
+</table> <h3 id="Explanation"> Explanation</h3> <p>The union is only as big as necessary to hold its largest member (additional unnamed trailing padding may also be added). The other members are allocated in the same bytes as part of that largest member.</p>
+<p>A pointer to a union can be cast to a pointer to each of its members (if a union has bit-field members, the pointer to a union can be cast to the pointer to the bit-field's underlying type). Likewise, a pointer to any member of a union can be cast to a pointer to the enclosing union.</p>
+<table class="t-rev-begin"> <tr class="t-rev t-since-c99">
+<td> <p>If the member used to access the contents of a union is not the same as the member last used to store a value, the object representation of the value that was stored is reinterpreted as an object representation of the new type (this is known as <i>type punning</i>). If the size of the new type is larger than the size of the last-written type, the contents of the excess bytes are unspecified (and may be a trap representation). Before C99 TC3 (DR 283) this behaviour was undefined, but commonly implemented this way.</p>
+</td> <td><span class="t-mark-rev t-since-c99">(since C99)</span></td>
+</tr> </table> <table class="t-rev-begin"> <tr class="t-rev t-since-c11">
+<td> <p>Similar to struct, an unnamed member of a union whose type is a union without <span class="t-spar">name</span> is known as <i>anonymous union</i>. Every member of an anonymous union is considered to be a member of the enclosing struct or union keeping their union layout. This applies recursively if the enclosing struct or union is also anonymous.</p>
+<div class="c source-c"><pre data-language="c">struct v
+{
+ union // anonymous union
+ {
+ struct { int i, j; }; // anonymous structure
+ struct { long k, l; } w;
+ };
+ int m;
+} v1;
+
+v1.i = 2; // valid
+v1.k = 3; // invalid: inner structure is not anonymous
+v1.w.k = 5; // valid</pre></div> <p>Similar to struct, the behavior of the program is undefined if union is defined without any named members (including those obtained via anonymous nested structs or unions).</p>
+</td> <td><span class="t-mark-rev t-since-c11">(since C11)</span></td>
+</tr> </table> <h3 id="Keywords"> Keywords</h3> <p><a href="../keyword/union" title="c/keyword/union"><code>union</code></a></p>
+<h3 id="Notes"> Notes</h3> <p>See <a href="struct_initialization" title="c/language/struct initialization">struct initialization</a> for the rules about initialization of structs and unions.</p>
+<h3 id="Example"> Example</h3> <div class="t-example"> <div class="c source-c"><pre data-language="c">#include &lt;assert.h&gt;
+#include &lt;stdint.h&gt;
+#include &lt;stdio.h&gt;
+
+int main(void)
+{
+ union S
+ {
+ uint32_t u32;
+ uint16_t u16[2];
+ uint8_t u8;
+ } s = {0x12345678}; // s.u32 is now the active member
+ printf("Union S has size %zu and holds %x\n", sizeof s, s.u32);
+ s.u16[0] = 0x0011; // s.u16 is now the active member
+ // reading from s.u32 or from s.u8 reinterprets the object representation
+// printf("s.u8 is now %x\n", s.u8); // unspecified, typically 11 or 00
+// printf("s.u32 is now %x\n", s.u32); // unspecified, typically 12340011 or 00115678
+
+ // pointers to all members of a union compare equal to themselves and the union
+ assert((uint8_t*)&amp;s == &amp;s.u8);
+
+ // this union has 3 bytes of trailing padding
+ union pad
+ {
+ char c[5]; // occupies 5 bytes
+ float f; // occupies 4 bytes, imposes alignment 4
+ } p = {.f = 1.23}; // the size is 8 to satisfy float's alignment
+ printf("size of union of char[5] and float is %zu\n", sizeof p);
+}</pre></div> <p>Possible output:</p>
+<div class="text source-text"><pre data-language="c">Union S has size 4 and holds 12345678
+size of union of char[5] and float is 8</pre></div> </div> <h3 id="References"> References</h3> <ul>
+<li> C23 standard (ISO/IEC 9899:2023): </li>
+<ul><li> 6.7.2.1 Structure and union specifiers (p: TBD) </li></ul>
+<li> C17 standard (ISO/IEC 9899:2018): </li>
+<ul><li> 6.7.2.1 Structure and union specifiers (p: 81-84) </li></ul>
+<li> C11 standard (ISO/IEC 9899:2011): </li>
+<ul><li> 6.7.2.1 Structure and union specifiers (p: 112-117) </li></ul>
+<li> C99 standard (ISO/IEC 9899:1999): </li>
+<ul><li> 6.7.2.1 Structure and union specifiers (p: 101-104) </li></ul>
+<li> C89/C90 standard (ISO/IEC 9899:1990): </li>
+<ul><li> 3.5.2.1 Structure and union specifiers </li></ul>
+</ul> <h3 id="See_also"> See also</h3> <table class="t-dsc-begin"> <tr class="t-dsc"> <td colspan="2"> <span><a href="https://en.cppreference.com/w/cpp/language/union" title="cpp/language/union">C++ documentation</a></span> for <span class=""><span>Union declaration</span></span> </td>
+</tr> </table> <div class="_attribution">
+ <p class="_attribution-p">
+ &copy; cppreference.com<br>Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.<br>
+ <a href="https://en.cppreference.com/w/c/language/union" class="_attribution-link">https://en.cppreference.com/w/c/language/union</a>
+ </p>
+</div>