-
Notifications
You must be signed in to change notification settings - Fork 160
/
enum.c
212 lines (171 loc) · 5.24 KB
/
enum.c
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#include "common.h"
int main(void) {
/*
# Terminology
- `E`: enumeration tag
- `E0`, `E1`: enumeration constants or memebers
*/
{
enum E {
E0,
E1
};
}
/*
# Values
# Enumeration constants
*/
{
/*
You can choose the values explicitly.
If you leave one out, it is the previous plus one.
If the first is left out, it is `0`.
- http://stackoverflow.com/questions/6434105/are-default-enum-values-in-c-the-same-for-all-compilers
- http://stackoverflow.com/questions/24946699/enums-in-c-what-assumptions-can-be-made-about-the-value-of-the-underlying-varia?lq=1
*/
{
enum E {
E0,
E1,
E2 = 3,
E3,
E4 = INT_MAX
/* ERROR: Overflow in enumeration values */
/*, E5*/
};
/* Enum types can then be cast to int. */
/* If unspecified, the first is 0. */
assert(E0 == 0);
assert(E1 == 1);
assert(E2 == 3);
/* Continue from the last one. */
assert(E3 == 4);
assert(E4 == INT_MAX);
// int can also be cast to enum?
{
{
enum E e = 0;
assert(e == E0);
}
{
enum E e = -1;
assert(e == -1);
}
}
/*
Repeat values.
Seems legal: http://stackoverflow.com/questions/5561142/duplicate-enum-values-in-c
*/
{
enum E {
E0 = 0,
E0_2 = 0
};
assert(E0 == E0_2);
}
}
/*
# Value size
# Value type
The maximum size is `int`, the actual data storage is implementation defined:
- http://stackoverflow.com/questions/366017/what-is-the-size-of-an-enum-in-c
- http://stackoverflow.com/questions/4879286/specifying-size-of-enum-type-in-c
- http://stackoverflow.com/questions/18090541/how-to-set-the-value-of-an-enumeration-constant-outside-the-range-of-int
In C++11, you can actually set the exact enum size.
*/
{
/* sizeof */
{
enum E {E1, E2};
assert(sizeof(enum E) == sizeof(int));
assert(sizeof(E1) == sizeof(int));
}
/* The largest value that can be portably stored is INT_MAX. */
{
enum E {E1 = INT_MAX};
/*enum E_BAD { E1 = INT_MAX + 1};*/
/*enum E_BAD { E1 = INT_MAX, A};*/
}
/*
Because size is unknown, it is not possible to forward declare
and use an enum: it is an incomplete type.
The situation is similar to `struct`, except that for `struct`
we can have pointers to a forward declaration.
But enums are not lvalues, so pointers to enums are useless.
*/
{
/* ERROR (pedantic): ISO C forbids forward references to enum types. */
/*enum Forward;*/
}
}
}
/* Declare enum variable. */
{
{
enum E { E0, E1 };
/* Like struct, you need enum. */
enum E e = E1;
}
/* Typedef combo. No need to type enum everywhere. */
{
/* Multi line */
enum E { E1, E2};
typedef enum E E;
E e;
/* Single line */
typedef enum F {g1, g2} F;
F f;
}
}
/* Nomemclature. */
{
enum E {E0};
/*
# Enumerator
# Member of an enum.
Synonyms.
Enumerator and "Member of an enum" are synonyms defined by the standard.
*/
}
/*
ERROR: only const expressions allowed for initialition.
When used, the values are constant expressions.
*/
{
const int i = 0;
/*enum Constexpr { N = i };*/
/*int is[N];*/
/* This is why enum values don't generate variable size arrays. */
{
enum N { N = 2 };
int is[N];
assert(sizeof(is) == 2 * sizeof(int));
}
}
/*
# Pointer to enum
# Address of enum
Enum values do not have address.
They are compile time constants, and cannot be modified.
GCC for example always inlines them: they never appear on object files.
*/
{
enum E {E0};
/* ERROR: lvalue required */
/* Enum constans are not lvalues. */
/*int *pe = &E0;*/
/* TODO legal but useless? */
enum E *pe;
}
/*
# Count elements of an ENUM.
Does not seem possible: http://stackoverflow.com/questions/2102582/how-can-i-count-the-items-in-an-enum
Possible workaround: add an extra element and rely on the increasing order.
Obvious downside: remote name conflict possibility.
*/
{
enum E {E1, E2, E_SIZE};
assert(E_SIZE == 2);
}
return EXIT_SUCCESS;
}