summaryrefslogtreecommitdiff
path: root/devdocs/c/language%2Fenum.html
blob: f472e47a31747a28e973cf0f40a29f343953932b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
    <h1 id="firstHeading" class="firstHeading">Enumerations</h1>            <p>An <i>enumerated type</i> is a distinct <a href="type" title="c/language/type">type</a> whose value is a value of its <i>underlying type</i> (see below), which includes the values of explicitly named constants (<i>enumeration constants</i>).</p>
<h3 id="Syntax"> Syntax</h3> <p>Enumerated type is declared using the following <i>enumeration specifier</i> as the <span class="t-spar">type-specifier</span> in the <a href="declarations" title="c/language/declarations">declaration grammar</a>:</p>
<table class="t-sdsc-begin">  <tr class="t-sdsc"> <td> <code>enum</code> <span class="t-spar">attr-spec-seq</span> <span class="t-mark">(optional)</span> <span class="t-spar">identifier</span> <span class="t-mark">(optional)</span> <code>{</code> <span class="t-spar">enumerator-list</span> <code>}</code> </td> <td> (1) </td> <td class="t-sdsc-nopad"> </td>
</tr>  <tr class="t-sdsc"> <td> <code>enum</code> <span class="t-spar">attr-spec-seq</span> <span class="t-mark">(optional)</span> <span class="t-spar">identifier</span> <span class="t-mark">(optional)</span> <code>:</code> <span class="t-spar">type</span> <code>{</code> <span class="t-spar">enumerator-list</span> <code>}</code> </td> <td> (2) </td> <td> <span class="t-mark-rev t-since-c23">(since C23)</span> </td>
</tr> 
</table> <div class="t-li1">
<span class="t-li">1)</span> Declares an enumeration without a fixed underlying type.</div> <div class="t-li1">
<span class="t-li">2)</span> Declares an enumeration of fixed underlying type <span class="t-spar">type</span>.</div> <p>where <span class="t-spar">enumerator-list</span> is a comma-separated list<span class="t-rev-inl t-since-c99"><span>(with trailing comma permitted)</span><span><span class="t-mark-rev t-since-c99">(since C99)</span></span></span> of <span class="t-spar">enumerator</span>, each of which has the form:</p>
<table class="t-sdsc-begin">  <tr class="t-sdsc"> <td> <span class="t-spar">enumeration-constant</span> <span class="t-spar">attr-spec-seq</span> <span class="t-mark">(optional)</span> </td> <td> (1) </td> <td class="t-sdsc-nopad"> </td>
</tr>  <tr class="t-sdsc"> <td> <span class="t-spar">enumeration-constant</span> <span class="t-spar">attr-spec-seq</span> <span class="t-mark">(optional)</span> <code>=</code> <span class="t-spar">constant-expression</span> </td> <td> (2) </td> <td class="t-sdsc-nopad"> </td>
</tr> 
</table> <p>where</p>
<table class="t-par-begin"> <tr class="t-par"> <td> <span class="t-spar">identifier</span>, <span class="t-spar">enumeration-constant</span> </td> <td> - </td> <td> identifiers that are introduced by this declaration </td>
</tr> <tr class="t-par"> <td> <span class="t-spar">constant-expression</span> </td> <td> - </td> <td> <a href="constant_expression" title="c/language/constant expression">integer constant expression</a> <span class="t-rev-inl t-until-c23"><span>whose value is representable as a value of type <span class="kw4">int</span></span><span><span class="t-mark-rev t-until-c23">(until C23)</span></span></span>. <span class="t-rev-inl t-since-c23"><span>If the enumeration has a fixed underlying type, representable as a value of <span class="t-spar">type</span></span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span> </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>, <ul>
<li> applied to the whole enumeration if appears after <code>enum</code>, </li>
<li> applied to the <span class="t-spar">enumerator</span> if appears after <span class="t-spar">enumeration-constant</span> </li>
</ul> </td>
</tr>
</table> <p>As with <a href="struct" title="c/language/struct">struct</a> or <a href="union" title="c/language/union">union</a>, a declaration that introduced an enumerated type and one or more enumeration constants may also declare one or more objects of that type or type derived from it.</p>
<div class="c source-c"><pre data-language="c">enum color { RED, GREEN, BLUE } c = RED, *cp = &amp;c;
// introduces the type enum color
// the integer constants RED, GREEN, BLUE
// the object c of type enum color
// the object cp of type pointer to enum color</pre></div> <h3 id="Explanation"> Explanation</h3> <p>Each <span class="t-spar">enumeration-constant</span> that appears in the body of an enumeration specifier becomes an <a href="constant_expression" title="c/language/constant expression">integer constant</a> <span class="t-rev-inl t-until-c23"><span>with type <span class="kw4">int</span></span><span><span class="t-mark-rev t-until-c23">(until C23)</span></span></span> in the enclosing scope and can be used whenever integer constants are required (e.g. as a case label or as a non-VLA array size).</p>
<table class="t-rev-begin"> <tr class="t-rev t-since-c23">
<td> <p>During the processing of each enumeration constant in the enumerator list, the type of the enumeration constant shall be:</p>
<ul>
<li> the previously declared type, if it is a redeclaration of the same enumeration constant; or, </li>
<li> the enumerated type, for an enumeration with fixed underlying type; or, </li>
<li> <span class="kw4">int</span>, if there are no previous enumeration constants in the enumerator list and no explicit = with a defining integer constant expression; or, </li>
<li> <span class="kw4">int</span>, if given explicitly with = and the value of the integer constant expression is representable by an int; or, </li>
<li> the type of the integer constant expression, if given explicitly with = and if the value of the integer constant expression is not representable by <span class="kw4">int</span>; or, </li>
<li> the type of the value from last enumeration constant with 1 added to it. If such an integer constant expression would overflow or wraparound the value of the previous enumeration constant from the addition of 1, the type takes on either: <ul>
<li> a suitably sized signed integer type (excluding the bit-precise signed integer types) capable of representing the value of the previous enumeration constant plus 1; or, </li>
<li> a suitably sized unsigned integer type (excluding the bit-precise unsigned integer types) capable of representing the value of the previous enumeration constant plus 1. </li>
</ul> </li>
</ul> <p>A signed integer type is chosen if the previous enumeration constant being added is of signed integer type. An unsigned integer type is chosen if the previous enumeration constant is of unsigned integer type. If there is no suitably sized integer type described previous which can represent the new value, then the enumeration has no type which is capable of representing all of its values.</p>
</td> <td><span class="t-mark-rev t-since-c23">(since C23)</span></td>
</tr> </table> <div class="c source-c"><pre data-language="c">enum color { RED, GREEN, BLUE } r = RED;
switch(r)
{
case RED:
    puts("red");
    break;
case GREEN:
    puts("green");
    break;
case BLUE:
    puts("blue");
    break;
}</pre></div> <p>If <span class="t-spar">enumeration-constant</span> is followed by <span class="t-spar">= constant-expression</span>, its value is the value of that constant expression. If <span class="t-spar">enumeration-constant</span> is not followed by <span class="t-spar">= constant-expression</span>, its value is the value one greater than the value of the previous enumerator in the same enumeration. The value of the first enumerator (if it does not use <span class="t-spar">= constant-expression</span>) is zero.</p>
<div class="c source-c"><pre data-language="c">enum Foo { A, B, C = 10, D, E = 1, F, G = F + C };
// A=0, B=1, C=10, D=11, E=1, F=2, G=12</pre></div> <p>The <span class="t-spar">identifier</span> itself, if used, becomes the name of the enumerated type in the tags <a href="name_space" title="c/language/name space">name space</a> and requires the use of the keyword enum (unless typedef'd into the ordinary name space).</p>
<div class="c source-c"><pre data-language="c">enum color { RED, GREEN, BLUE };
enum color r = RED; // OK
// color x = GREEN: // Error: color is not in ordinary name space
typedef enum color color_t;
color_t x = GREEN; // OK</pre></div> <p>Each enumerated type <span class="t-rev-inl t-since-c23"><span>without a fixed underlying type</span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span> is <a href="type#Compatible_types" title="c/language/type">compatible</a> with one of: <span class="kw4">char</span>, a signed integer type, or an unsigned integer type <span class="t-rev-inl t-since-c23"><span>(excluding bool and the bit-precise integer types)</span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span>. It is implementation-defined which type is compatible with any given enumerated type, but whatever it is, it must be capable of representing all enumerator values of that enumeration. <span class="t-rev-inl t-since-c23"><span>For all enumerations with a fixed underlying type, the enumerated type is compatible with the underlying type of the enumeration.</span><span><span class="t-mark-rev t-since-c23">(since C23)</span></span></span></p>
<table class="t-rev-begin"> <tr class="t-rev t-since-c23">
<td> <p>The enumeration member type for an enumerated type without fixed underlying type upon completion is:</p>
<ul>
<li> <span class="kw4">int</span> if all the values of the enumeration are representable as an <span class="kw4">int</span>; or, </li>
<li> the enumerated type. </li>
</ul> </td> <td><span class="t-mark-rev t-since-c23">(since C23)</span></td>
</tr> <tr class="t-rev t-since-c23">
<td>All enumerations have an underlying type. The underlying type can be explicitly specified using an enum-type-specifier and is its fixed underlying type. If it is not explicitly specified, the underlying type is the enumeration’s compatible type, which is either a signed or unsigned integer type, or <span class="kw4">char</span>. </td> <td><span class="t-mark-rev t-since-c23">(since C23)</span></td>
</tr> </table> <p>Enumerated types are integer types, and as such can be used anywhere other integer types can, including in <a href="conversion" title="c/language/conversion">implicit conversions</a> and <a href="operator_arithmetic" title="c/language/operator arithmetic">arithmetic operators</a>.</p>
<div class="c source-c"><pre data-language="c">enum { ONE = 1, TWO } e;
long n = ONE; // promotion
double d = ONE; // conversion
e = 1.2; // conversion, e is now ONE
e = e + 1; // e is now TWO</pre></div> <h3 id="Notes"> Notes</h3> <p>Unlike <a href="struct" title="c/language/struct">struct</a> or <a href="union" title="c/language/union">union</a>, there are no forward-declared enums in C:</p>
<div class="c source-c"><pre data-language="c">enum Color; // Error: no forward-declarations for enums in C
enum Color { RED, GREEN, BLUE };</pre></div> <p>Enumerations permit the declaration of named constants in a more convenient and structured fashion than does <code>#define</code>; they are visible in the debugger, obey scope rules, and participate in the type system.</p>
<div class="c source-c"><pre data-language="c">#define TEN 10
struct S { int x : TEN; }; // OK</pre></div> <p>or</p>
<div class="c source-c"><pre data-language="c">enum { TEN = 10 };
struct S { int x : TEN; }; // also OK</pre></div> <p>Since C23 <a href="constexpr" title="c/language/constexpr">constexpr</a> can be used for the same purpose:</p>
<div class="c source-c"><pre data-language="c">constexpr int TEN = 10;
struct S { int x : TEN; }; // also OK</pre></div> <p>Moreover, as a <a href="struct" title="c/language/struct">struct</a> or <a href="union" title="c/language/union">union</a> does not establish its scope in C, an enumeration type and its enumeration constants may be introduced in the member specification of the former, and their scope is the same as of the former, afterwards.</p>
<div class="c source-c"><pre data-language="c">struct Element
{
    int z;
    enum State { SOLID, LIQUID, GAS, PLASMA } state;
} oxygen = { 8, GAS };
 
// type enum State and its enumeration constants stay visible here, e.g.
void foo(void)
{
    enum State e = LIQUID; // OK
    printf("%d %d %d ", e, oxygen.state, PLASMA); // prints 1 2 3
}</pre></div> <h3 id="Example"> Example</h3> <div class="t-example"> <div class="c source-c"><pre data-language="c">#include &lt;stdio.h&gt;
 
int main(void)
{
    enum TV { FOX = 11, CNN = 25, ESPN = 15, HBO = 22, MAX = 30, NBC = 32 };
 
    printf("List of cable stations:\n");
    printf(" FOX: \t%2d\n", FOX);
    printf(" HBO: \t%2d\n", HBO);
    printf(" MAX: \t%2d\n", MAX);
}</pre></div> <p>Output:</p>
<div class="text source-text"><pre data-language="c">List of cable stations:
 FOX:   11
 HBO:   22
 MAX:   30</pre></div> </div> <h3 id="References"> References</h3>  <ul>
<li> C23 standard (ISO/IEC 9899:2023): </li>
<ul>
<li> 6.2.5/21 Types (p: 39) </li>
<li> 6.7.2.2 Enumeration specifiers (p: 107-112) </li>
</ul>
<li> C17 standard (ISO/IEC 9899:2018): </li>
<ul>
<li> 6.2.5/16 Types (p: 32) </li>
<li> 6.7.2.2 Enumeration specifiers (p: 84-85) </li>
</ul>
<li> C11 standard (ISO/IEC 9899:2011): </li>
<ul>
<li> 6.2.5/16 Types (p: 41) </li>
<li> 6.7.2.2 Enumeration specifiers (p: 117-118) </li>
</ul>
<li> C99 standard (ISO/IEC 9899:1999): </li>
<ul>
<li> 6.2.5/16 Types (p: 35) </li>
<li> 6.7.2.2 Enumeration specifiers (p: 105-106) </li>
</ul>
<li> C89/C90 standard (ISO/IEC 9899:1990): </li>
<ul>
<li> 3.1.2.5 Types </li>
<li> 3.5.2.2 Enumeration specifiers </li>
</ul>
</ul>                        <h3 id="Keywords"> Keywords</h3> <p><a href="../keyword/enum" title="c/keyword/enum"><code>enum</code></a></p>
<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/enum" title="cpp/language/enum">C++ documentation</a></span> for <span class=""><span>enumeration 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/enum" class="_attribution-link">https://en.cppreference.com/w/c/language/enum</a>
  </p>
</div>