with the types struct s2, t2, the type pointed to by tp2, or int.
6 EXAMPLE 3 The following obscure constructions
typedef signed int t;
typedef int plain;
struct tag {
unsigned t:4;
const t:5;
plain r:5;
};
declare a typedef name t with type signed int, a typedef name plain with type int, and a structure with three bit-field
members, one named t that contains values in the range [0, 15], an unnamed const-qualified bit-field which (if it could
be accessed) would contain values in either the range [−15, +15] or [−16, +15], and one named r that contains values in
one of the ranges [0, 31], [−15, +15], or [−16, +15]. (The choice of range is implementation-defined.) The first two bit-field
declarations differ in that unsigned is a type specifier (which forces t to be the name of a structure member), while const is
a type qualifier (which modifies t which is still visible as a typedef name). If these declarations are followed in an inner scope
by
t f(t (t));
long t;
then a function f is declared with type "function returning signed int with one unnamed parameter with type pointer
to function returning signed int with one unnamed parameter with type signed int", and an identifier t with type
long int.
7 EXAMPLE 4 On the other hand, typedef names can be used to improve code readability. All three of the following
declarations of the signal function specify exactly the same type, the first without making use of any typedef names.
typedef void fv(int), (*pfv)(int);
void (*signal(int, void (*)(int)))(int);
fv *signal(int, fv *);
pfv signal(int, pfv);
8 EXAMPLE 5 If a typedef name denotes a variable length array type, the length of the array is fixed at the time the typedef
name is defined, not each time it is used:
void copyt(int n)
{
typedef int B[n]; // B is n ints, n evaluated now
n += 1;
B a; // a is n ints, n without += 1
int b[n]; // a and b are different sizes
for (int i = 1; i < n; i++)
a[i-1] = b[i];
}
6.7.9 [Type inference]
1 Constraints
A declaration for which the type is inferred shall contain the storage-class specifier auto.
Description
2 For such a declaration that is the definition of an object the init-declarator shall have one of the forms
direct-declarator = assignment-expression
direct-declarator = { assignment-expression }
direct-declarator = { assignment-expression , }
The declared type is the type of the assignment expression after lvalue, array to pointer or function
to pointer conversion, additionally qualified by qualifiers and amended by attributes as they appear
in the declaration specifiers, if any[179] . If the direct declarator is not of the form
identifier attribute-specifier-sequenceopt
, possibly enclosed in balanced pairs of parentheses, the behavior is undefined.
Footnote 179) The scope rules as described in 6.2.1 also prohibit the use of the identifier of the declarator within the assignment
expression.
3 NOTE Such a declaration that also defines a structure or union type violates a constraint. Here, the identifier a which is not
ordinary but in the name space of the structure type is declared.
auto p = (struct { int a; } *)0;
Even a forward declaration of a structure tag
struct s;
auto p = (struct s { int a; } *)0;
would not change that situation. A direct use of the structure definition as the type specifier ensures the validity of the
declaration.
struct s { int a; } * p = 0;
4 EXAMPLE 1 Consider the following file scope definitions:
static auto a = 3.5;
auto p = &a;
They are interpreted as if they had been written as:
static double a = 3.5;
double * p = &a;
So effectively a is a double and p is a double*. Note that the restrictions on the syntax of such declarations does not allow the
declarator to be *p , but that the final type here nevertheless is a pointer type.
5 EXAMPLE 2 The scope of the identifier for which the type is inferred only starts after the end of the initializer (6.2.1), so
the assignment expression cannot use the identifier to refer to the object or function that is declared, for example to take its
address. Any use of the identifier in the initializer is invalid, even if an entity with the same name exists in an outer scope.
{
double a = 7;
double b = 9;
{
double b = b * b; // undefined, uses uninitialized
// variable without address
printf("%g\n", a); // valid, uses "a" from outer scope, prints 7
auto a = a * a; // invalid, "a" from outer scope is already
shadowed
}
{
auto b = a * a; // valid, uses "a" from outer scope
auto a = b; // valid, shadows "a" from outer scope
// ...
printf("%g\n", a); // valid, uses "a" from inner scope, prints 49
}
// ...
}
6 EXAMPLE 3 In the following, declarations of pA and qA are valid. The type of A after array-to-pointer conversion is a pointer
type, and qA is a pointer to array.
double A[3] = { 0 };
auto pA = A;
auto qA = &A;
7 EXAMPLE 4 Type inference can be used to capture the type of a call to a type-generic function. It ensures that the same type
as the argument x is used.
#include <tgmath.h>
auto y = cos(x);
If instead the type of y is explicitly specified to a different type than x, a diagnosis of the mismatch is not enforced.
8 EXAMPLE 5 A type-generic macro that generalizes the div functions (<IP_ADDRESS>) is defined and used as follows.
#define div(X, Y) _Generic((X)+(Y), int: div, long: ldiv, long long: lldiv)((X),
(Y))
auto z = div(x, y);
auto q = z.quot;
auto r = z.rem;
9 EXAMPLE 6 Definitions of objects with inferred type are valid in all contexts that allow the initializer syntax as described.
In particular they can be used to ensure type safety of for-loop controlling expressions.
for (auto i = j; i < 2*j; ++i) {
// ...
}
Here, regardless of the integer rank or signedness of the type of j, i will have the non-atomic unqualified type of j. So, after
lvalue conversion and possible promotion, the two operands of the < operator in the controlling expression are guaranteed to
have the same type, and, in particular, the same signedness.
6.7.10 [Initialization]
1 Syntax
braced-initializer:
{ }
{ initializer-list }
{ initializer-list , }
initializer:
assignment-expression
braced-initializer
initializer-list:
designationopt initializer
initializer-list , designationopt initializer
designation:
designator-list =
designator-list:
designator
designator-list designator
designator:
[ constant-expression ]
. identifier
2 An empty brace pair ({}) is called an empty initializer and is referred to as empty initialization.
Constraints
3 No initializer shall attempt to provide a value for an object not contained within the entity being
initialized.
4 The type of the entity to be initialized shall be an array of unknown size or a complete object type.
An entity of variable length array type shall not be initialized except by an empty initializer. An
array of unknown size shall not be initialized by an empty initializer.
5 All the expressions in an initializer for an object that has static or thread storage duration or is
declared with the constexpr storage-class specifier shall be constant expressions or string literals.
6 If the declaration of an identifier has block scope, and the identifier has external or internal linkage,
the declaration shall have no initializer for the identifier.
7 If a designator has the form
[ constant-expression ]
then the current object (defined below) shall have array type and the expression shall be an integer
constant expression. If the array is of unknown size, any nonnegative value is valid.
8 If a designator has the form
. identifier
then the current object (defined below) shall have structure or union type and the identifier shall be
the name of a member of that type.
Semantics
9 An initializer specifies the initial value stored in an object. For objects with atomic type additional
restrictions apply, see 7.17.2 and 7.17.8.
10 Except where explicitly stated otherwise, for the purposes of this subclause unnamed members
of objects of structure and union type do not participate in initialization. Unnamed members of
structure objects have indeterminate representation even after initialization.
11 If an object that has automatic storage duration is initialized with an empty initializer, its value
is the same as the initialization of a static storage duration object. Otherwise, if an object that has
automatic storage duration is not initialized explicitly, its representation is indeterminate. If an
object that has static or thread storage duration is not initialized explicitly, or is initialized with an
empty initializer, then default initialization:
— if it has pointer type, it is initialized to a null pointer;
— if it has decimal floating type, it is initialized to (positive or unsigned) zero, and the quantum
exponent is implementation-defined[180] ;
— if it has arithmetic type, and it does not have decimal floating type, it is initialized to (positive
or unsigned) zero;
— if it is an aggregate, every member is initialized (recursively) according to these rules, and any
padding is initialized to zero bits;
— if it is a union, the first named member is initialized (recursively) according to these rules, and
any padding is initialized to zero bits;
Footnote 180) A representation with all bits zero results in a decimal floating-point zero with the most negative exponent.
12 The initializer for a scalar shall be a single expression, optionally enclosed in braces, or it shall be
an empty initializer. If the initializer is the empty initializer, the initial value is the same as the
initialization of a static storage duration object. Otherwise, the initial value of the object is that of the
expression (after conversion); the same type constraints and conversions as for simple assignment
apply, taking the type of the scalar to be the unqualified version of its declared type.
13 The rest of this subclause deals with initializers for objects that have aggregate or union type.
14 The initializer for a structure or union object that has automatic storage duration shall be either
an initializer list as described below, or a single expression that has compatible structure or union
type. In the latter case, the initial value of the object, including unnamed members, is that of the
expression.
15 An array of character type may be initialized by a character string literal or UTF-8 string literal,
optionally enclosed in braces. Successive bytes of the string literal (including the terminating null
character if there is room or if the array is of unknown size) initialize the elements of the array.
16 An array with element type compatible with a qualified or unqualified version of wchar_t, char16_t,
or char32_t may be initialized by a wide string literal with the corresponding encoding prefix (L,
u, or U, respectively), optionally enclosed in braces. Successive wide characters of the wide string
literal (including the terminating null wide character if there is room or if the array is of unknown
size) initialize the elements of the array.
17 Otherwise, the initializer for an object that has aggregate or union type shall be a brace-enclosed list
of initializers for the elements or named members.
18 Each brace-enclosed initializer list has an associated current object. When no designations are present,
subobjects of the current object are initialized in order according to the type of the current object:
array elements in increasing subscript order, structure members in declaration order, and the first
named member of a union.[181] In contrast, a designation causes the following initializer to begin
initialization of the subobject described by the designator. Initialization then continues forward in
order, beginning with the next subobject after that described by the designator.[182]
Footnote 181) If the initializer list for a subaggregate or contained union does not begin with a left brace, its subobjects are initialized as
usual, but the subaggregate or contained union does not become the current object: current objects are associated only with
brace-enclosed initializer lists.
Footnote 182) After a union member is initialized, the next object is not the next member of the union; instead, it is the next subobject of
an object containing the union.
19 Each designator list begins its description with the current object associated with the closest sur-
rounding brace pair. Each item in the designator list (in order) specifies a particular member of its
current object and changes the current object for the next designator (if any) to be that member.[183]
The current object that results at the end of the designator list is the subobject to be initialized by the
following initializer.
Footnote 183) Thus, a designator can only specify a strict subobject of the aggregate or union that is associated with the surrounding
brace pair. Note, too, that each separate designator list is independent.
20 The initialization shall occur in initializer list order, each initializer provided for a particular subobject
overriding any previously listed initializer for the same subobject;[184] all subobjects that are not
initialized explicitly shall be initialized implicitly the same as objects that have static storage duration.
Footnote 184) Any initializer for the subobject which is overridden and so not used to initialize that subobject might not be evaluated at
all.
21 If the aggregate or union contains elements or members that are aggregates or unions, these rules
apply recursively to the subaggregates or contained unions. If the initializer of a subaggregate or
contained union begins with a left brace, the initializers enclosed by that brace and its matching right
brace initialize the elements or members of the subaggregate or the contained union. Otherwise, only
enough initializers from the list are taken to account for the elements or members of the subaggregate
or the first member of the contained union; any remaining initializers are left to initialize the next
element or member of the aggregate of which the current subaggregate or contained union is a part.
22 If there are fewer initializers in a brace-enclosed list than there are elements or members of an
aggregate, or fewer characters in a string literal used to initialize an array of known size than there
are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as
objects that have static storage duration.
23 If an array of unknown size is initialized, its size is determined by the largest indexed element with
an explicit initializer. The array type is completed at the end of its initializer list.
24 The evaluations of the initialization list expressions are indeterminately sequenced with respect to
one another and thus the order in which any side effects occur is unspecified.[185]
Footnote 185) In particular, the evaluation order need not be the same as the order of subobject initialization.
25 EXAMPLE 1 Provided that <complex.h> has been #included, the declarations
int i = 3.5;
double complex c = 5 + 3 * I;
define and initialize i with the value 3 and c with the value 5.0 + i3.0.
26 EXAMPLE 2 The declaration
int x[] = { 1, 3, 5 };
defines and initializes x as a one-dimensional array object that has three elements, as no size was specified and there are three
initializers.
27 EXAMPLE 3 The declaration
int y[4][3] = {
{ 1, 3, 5 },
{ 2, 4, 6 },
{ 3, 5, 7 },
};
is a definition with a fully bracketed initialization: 1, 3, and 5 initialize the first row of y (the array object y[0]), namely
y[0][0], y[0][1], and y[0][2]. Likewise the next two lines initialize y[1] and y[2]. The initializer ends early, so y[3] is
initialized with zeros. Precisely the same effect could have been achieved by
int y[4][3] = {
1, 3, 5, 2, 4, 6, 3, 5, 7
};
The initializer for y[0] does not begin with a left brace, so three items from the list are used. Likewise the next three are
taken successively for y[1] and y[2].
28 EXAMPLE 4 The declaration
int z[4][3] = {
{ 1 }, { 2 }, { 3 }, { 4 }
};
initializes the first column of z as specified and initializes the rest with zeros.
29 EXAMPLE 5 The declaration
struct { int a[3], b; } w[] = { { 1 }, 2 };
is a definition with an inconsistently bracketed initialization. It defines an array with two element structures: w[0].a[0] is 1
and w[1].a[0] is 2; all the other elements are zero.
30 EXAMPLE 6 The declaration
short q[4][3][2] = {
{ 1 },
{ 2, 3 },
{ 4, 5, 6 }
};
contains an incompletely but consistently bracketed initialization. It defines a three-dimensional array object: q[0][0][0]
is 1, q[1][0][0] is 2, q[1][0][1] is 3, and 4, 5, and 6 initialize q[2][0][0], q[2][0][1], and q[2][1][0], respectively;
all the rest are zero. The initializer for q[0][0] does not begin with a left brace, so up to six items from the current list
could be used. There is only one, so the values for the remaining five elements are initialized with zero. Likewise, the
initializers for q[1][0] and q[2][0] do not begin with a left brace, so each uses up to six items, initializing their respective
two-dimensional subaggregates. If there had been more than six items in any of the lists, a diagnostic message would have
been issued. The same initialization result could have been achieved by:
short q[4][3][2] = {
1, 0, 0, 0, 0, 0,
2, 3, 0, 0, 0, 0,
4, 5, 6
};
or by:
short q[4][3][2] = {
{
{ 1 },
},
{
{ 2, 3 },
},
{
{ 4, 5 },
{ 6 },
}
};
in a fully bracketed form.
31 Note that the fully bracketed and minimally bracketed forms of initialization are, in general, less likely to cause confusion.
32 EXAMPLE 7 One form of initialization that completes array types involves typedef names. Given the declaration
typedef int A[]; // OK - declared with block scope
the declaration
A a = { 1, 2 }, b = { 3, 4, 5 };
is identical to
int a[] = { 1, 2 }, b[] = { 3, 4, 5 };
due to the rules for incomplete types.
33 EXAMPLE 8 The declaration
char s[] = "abc", t[3] = "abc";
defines "plain" char array objects s and t whose elements are initialized with character string literals. This declaration is
identical to
char s[] = { ’a’, ’b’, ’c’, ’\0’ },
t[] = { ’a’, ’b’, ’c’ };
The contents of the arrays are modifiable. On the other hand, the declaration
char *p = "abc";
defines p with type "pointer to char" and initializes it to point to an object with type "array of char" with length 4 whose
elements are initialized with a character string literal. If an attempt is made to use p to modify the contents of the array, the
behavior is undefined.
34 EXAMPLE 9 Arrays can be initialized to correspond to the elements of an enumeration by using designators:
enum { member_one, member_two };
const char *nm[] = {
[member_two] = "member two",
[member_one] = "member one",
};
35 EXAMPLE 10 Structure members can be initialized to nonzero values without depending on their order:
div_t answer = {.quot = 2, .rem = -1 };
36 EXAMPLE 11 Designators can be used to provide explicit initialization when unadorned initializer lists might be misunder-
stood:
struct { int a[3], b; } w[] =
{ [0].a = {1}, [1].a[0] = 2 };
37 EXAMPLE 12
struct T {
int k;
int l;
};
struct S {
int i;
struct T t;
};
struct T x = {.l = 43, .k = 42, };
void f(void)
{
struct S l = { 1, .t = x, .t.l = 41, };
}
The value of l.t.k is 42, because implicit initialization does not override explicit initialization.
38 EXAMPLE 13 Space can be "allocated" from both ends of an array by using a single designator:
int a[MAX] = {
1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0
};
39 In the above, if MAX is greater than ten, there will be some zero-valued elements in the middle; if it is less than ten, some of
the values provided by the first five initializers will be overridden by the second five.
40 EXAMPLE 14 Any member of a union can be initialized:
union { /* ... */ } u = {.any_member = 42 };
Forward references: common definitions <stddef.h> (7.21).
6.7.11 [Static assertions]
1 Syntax
static_assert-declaration:
static_assert ( constant-expression , string-literal ) ;
static_assert ( constant-expression ) ;
Constraints
2 The constant expression shall compare unequal to 0.
Semantics
3 The constant expression shall be an integer constant expression. If the value of the constant expres-
sion compares unequal to 0, the declaration has no effect. Otherwise, the constraint is violated and
the implementation shall produce a diagnostic message which should include the text of the string
literal, if present.
Forward references: diagnostics (7.2).
6.7.12 [Attributes]
1 Attributes specify additional information for various source constructs such as types, variables,
identifiers, or blocks. They are identified by an attribute token, which can either be a attribute prefixed
token (for implementation-specific attributes) or a standard attribute specified by an identifier (for
attributes specified in this document).
2 Support for any of the standard attributes specified in this document is implementation-defined
and optional. For an attribute token (including an attribute prefixed token) not specified in this
document, the behavior is implementation-defined. Any attribute token that is not supported by the
implementation is ignored.
3 Attributes are said to appertain to some source construct, identified by the syntactic context where
they appear, and for each individual attribute, the corresponding clause constrains the syntactic
context in which this appertainance is valid. The attribute specifier sequence appertaining to some
source construct shall contain only attributes that are allowed to apply to that source construct.
4 In all aspects of the language, a standard attribute specified by this document as an identifier attr
and an identifier of the form __attr__ shall behave the same when used as an attribute token,
except for the spelling.[186]
Recommended practice
Footnote 186) Thus, the attributes [[nodiscard]] and [[__nodiscard__]] can be freely interchanged. Implementations are encour-
aged to behave similarly for attribute tokens (including attribute prefixed tokens) they provide.
5 It is recommended that implementations support all standard attributes as defined in this document.
<IP_ADDRESS> [General]
1 Syntax
attribute-specifier-sequence:
attribute-specifier-sequenceopt attribute-specifier
attribute-specifier:
[ [ attribute-list ] ]
attribute-list:
attributeopt
attribute-list , attributeopt
attribute:
attribute-token attribute-argument-clauseopt
attribute-token:
standard-attribute
attribute-prefixed-token
standard-attribute:
identifier
attribute-prefixed-token:
attribute-prefix :: identifier
attribute-prefix:
identifier
attribute-argument-clause:
( balanced-token-sequenceopt )
balanced-token-sequence:
balanced-token
balanced-token-sequence balanced-token
balanced-token:
( balanced-token-sequenceopt )
[ balanced-token-sequenceopt ]
{ balanced-token-sequenceopt }
any token other than a parenthesis, a bracket, or a brace
Constraints
2 The identifier in a standard attribute shall be one of:
deprecated maybe_unused noreturn unsequenced
fallthrough nodiscard _Noreturn reproducible
Semantics
3 An attribute specifier that contains no attributes has no effect. The order in which attribute tokens
appear in an attribute list is not significant. If a keyword (6.4.1) that satisfies the syntactic require-
ments of an identifier (6.4.2) is contained in an attribute token, it is considered an identifier. A strictly
conforming program using a standard attribute remains strictly conforming in the absence of that
attribute. [187]
Footnote 187) Standard attributes specified by this document can be parsed but ignored by an implementation without changing the
semantics of a correct program; the same is not true for attributes not specified by this document.
4 NOTE For each standard attribute, the form of the balanced token sequence, if any, will be specified.
Recommended Practice
5 Each implementation should choose a distinctive name for the attribute prefix in an attribute
prefixed token. Implementations should not define attributes without an attribute prefix unless it is
a standard attribute as specified in this document.
6 EXAMPLE 1 Suppose that an implementation chooses the attribute prefix hal and provides specific attributes named daisy
and rosie.
[[deprecated, hal::daisy]] double nine1000(double);
[[deprecated]] [[hal::daisy]] double nine1000(double);
[[deprecated]] double nine1000 [[hal::daisy]] (double);
Then all the following declarations should be equivalent aside from the spelling:
[[__deprecated__, __hal__::__daisy__]] double nine1000(double);
[[__deprecated__]] [[__hal__::__daisy__]] double nine1000(double);
[[__deprecated__]] double nine1000 [[__hal__::__daisy__]] (double);
These use the alternate spelling that is required for all standard attributes and recommended for prefixed attributes. These
may be better-suited for use in header files, where the use of the alternate spelling avoids naming conflicts with user-provided
macros.
7 EXAMPLE 2 For the same implementation, the following two declarations are equivalent, because the ordering inside
attribute lists is not important.
[[hal::daisy, hal::rosie]] double nine999(double);
[[hal::rosie, hal::daisy]] double nine999(double);
On the other hand the following two declarations are not equivalent, because the ordering of different attribute specifiers
may affect the semantics.
[[hal::daisy]] [[hal::rosie]] double nine999(double);
[[hal::rosie]] [[hal::daisy]] double nine999(double); // may have different semantics
<IP_ADDRESS> [The nodiscard attribute]
1 Constraints
The nodiscard attribute shall be applied to the identifier in a function declaration or to the definition
of a structure, union, or enumeration type. If an attribute argument clause is present, it shall have
the form:
( string-literal )
Semantics
2 The __has_c_attribute conditional inclusion expression (6.10.1) shall return the value 202003L
when given nodiscard as the pp-tokens operand.
3 A name or entity declared without the nodiscard attribute can later be redeclared with the attribute
and vice versa. An entity is considered marked after the first declaration that marks it.
Recommended Practice
4 A nodiscard call is a function call expression that calls a function previously declared with attribute
nodiscard, or whose return type is a structure, union, or enumeration type marked with attribute
nodiscard. Evaluation of a nodiscard call as a void expression (6.8.3) is discouraged unless explicitly
cast to void. Implementations are encouraged to issue a diagnostic in such cases. This is typically
because immediately discarding the return value of a nodiscard call has surprising consequences.
5 The diagnostic message should include text provided by the string literal within the attribute
argument clause of any nodiscard attribute applied to the name or entity.
6 EXAMPLE 1
struct [[nodiscard]] error_info { /*...*/ };
struct error_info enable_missile_safety_mode(void);
void launch_missiles(void);
void test_missiles(void) {
enable_missile_safety_mode();
launch_missiles();
}
A diagnostic for the call to enable_missile_safety_mode is encouraged.
7 EXAMPLE 2
[[nodiscard]] int important_func(void);
void call(void) {
int i = important_func();
}
No diagnostic for the call to important_func is encouraged despite the value of i not being used.
8 EXAMPLE 3
[[nodiscard("must check armed state")]]
bool arm_detonator(int);
void call(void) {
arm_detonator(3);
detonate();
}
A diagnostic for the call toarm_detonator using the string literal "must check armed state" from the attribute argument
clause is encouraged.
<IP_ADDRESS> [The maybe_unused attribute]
1 Constraints
The maybe_unused attribute shall be applied to the declaration of a structure, a union, a typedef
name, a variable, a structure or union member, a function, an enumeration, an enumerator, or a label.
No attribute argument clause shall be present.
Semantics
2 The maybe_unused attribute indicates that a name or entity is possibly intentionally unused.
3 The __has_c_attribute conditional inclusion expression (6.10.1) shall return the value 202106L
when given maybe_unused as the pp-tokens operand.
A name or entity declared without the maybe_unused attribute can later be redeclared with the
attribute and vice versa. An entity is considered marked with the attribute after the first declaration
that marks it.
Recommended Practice
4 For an entity marked maybe_unused, implementations are encouraged not to emit a diagnostic that
the entity is unused, or that the entity is used despite the presence of the attribute.
5 EXAMPLE
[[maybe_unused]] void f([[maybe_unused]] int i) {
[[maybe_unused]] int j = i + 100;
assert(j);
}
Implementations are encouraged not to diagnose that j is unused, whether or not NDEBUG is defined.
<IP_ADDRESS> [The deprecated attribute]
1 Constraints
The deprecated attribute shall be applied to the declaration of a structure, a union, a typedef name,
a variable, a structure or union member, a function, an enumeration, or an enumerator.
2 If an attribute argument clause is present, it shall have the form:
( string-literal )
Semantics
3 The deprecated attribute can be used to mark names and entities whose use is still allowed, but is
discouraged for some reason. [188]
Footnote 188) In particular, deprecated is appropriate for names and entities that are obsolescent, insecure, unsafe, or otherwise unfit
for purpose.
4 The __has_c_attribute conditional inclusion expression (6.10.1) shall return the value 201904L
when given deprecated as the pp-tokens operand.
5 A name or entity declared without the deprecated attribute can later be redeclared with the attribute
and vice versa. An entity is considered marked with the attribute after the first declaration that
marks it.
Recommended Practice
6 Implementations should use the deprecated attribute to produce a diagnostic message in case the
program refers to a name or entity other than to declare it, after a declaration that specifies the
attribute, when the reference to the name or entity is not within the context of a related deprecated
entity. The diagnostic message should include text provided by the string literal within the attribute
argument clause of any deprecated attribute applied to the name or entity.
7 EXAMPLE
struct [[deprecated]] S {
int a;
};
enum [[deprecated]] E1 {
one
};
enum E2 {
two [[deprecated("use ’three’ instead")]],
three
};
[[deprecated]] typedef int Foo;
void f1(struct S s) { // Diagnose use of S
int i = one; // Diagnose use of E1
int j = two; // Diagnose use of two: "use ’three’ instead"
int k = three;
Foo f; // Diagnose use of Foo
}
[[deprecated]] void f2(struct S s) {
int i = one;
int j = two;
int k = three;
Foo f;
}
struct [[deprecated]] T {
Foo f;
struct S s;
};
Implementations are encouraged to diagnose the use of deprecated entities within a context which is not itself deprecated, as
indicated for function f1, but not to diagnose within function f2 and struct T, as they are themselves deprecated.
<IP_ADDRESS> [The fallthrough attribute]
1 Constraints
The attribute token fallthrough shall only appear in an attribute declaration (6.7); such a declara-
tion is a fallthrough declaration. No attribute argument clause shall be present. A fallthrough decla-
ration may only appear within an enclosing switch statement (<IP_ADDRESS>). The next block item(6.8.2)
that would be encountered after a fallthrough declaration shall be a case label or default label
associated with the smallest enclosing switch statement.
Semantics
2 The __has_c_attribute conditional inclusion expression (6.10.1) shall return the value 201904L
when given fallthrough as the pp-tokens operand.
Recommended Practice
3 The use of a fallthrough declaration is intended to suppress a diagnostic that an implementation
might otherwise issue for a case or default label that is reachable from another case or default
label along some path of execution. Implementations are encouraged to issue a diagnostic if a
fallthrough declaration is not dynamically reachable.
4 EXAMPLE
void f(int n) {
void g(void), h(void), i(void);
switch (n) {
case 1: /* diagnostic on fallthrough discouraged */
case 2:
g();
[[fallthrough]];
case 3: /* diagnostic on fallthrough discouraged */
h();
case 4: /* fallthrough diagnostic encouraged */
i();
[[fallthrough]]; /* constraint violation */
}
}
<IP_ADDRESS> [The noreturn and _Noreturn attributes]
1 Description
When _Noreturn is used as an attribute token (instead of a function specifier), the constraints and
semantics are identical to that of the noreturn attribute token. Use of _Noreturn as an attribute
token is an obsolescent feature[189] .
Constraints
Footnote 189) [[_Noreturn]] and [[noreturn]] are equivalent attributes to support code that includes <stdnoreturn.h>, because
that header defines noreturn as a macro that expands to _Noreturn .
2 The noreturn attribute shall be applied to the identifier in a function declaration. No attribute
argument clause shall be present.
Semantics
3 The first declaration of a function shall specify the noreturn attribute if any declaration of that
function specifies the noreturn attribute. If a function is declared with the noreturn attribute in
one translation unit and the same function is declared without the noreturn attribute in another
translation unit, the behavior is undefined.
4 If a function f is called where f was previously declared with the noreturn attribute and f eventually
returns, the behavior is undefined.
5 The __has_c_attribute conditional inclusion expression (6.10.1) shall return the value 202202L
when given noreturn as the pp-tokens operand.
Recommended Practice
6 The implementation should produce a diagnostic message for a function declared with a noreturn
attribute that appears to be capable of returning to its caller.
7 EXAMPLE
[[noreturn]] void f(void) {
abort(); // ok
}
[[noreturn]] void g(int i) { // causes undefined behavior if i <= 0
if (i > 0) abort();
}
[[noreturn]] int h(void);
Implementations are encouraged to diagnose the definition of g() because it is capable of returning to its caller. Implementa-
tions are similarly encouraged to diagnose the declaration of h() because it appears capable of returning to its caller due to
the non-void return type.
<IP_ADDRESS> [Standard attributes for function types]
1 Constraints
The identifier in a standard function type attribute shall be one of:
unsequenced reproducible
2 An attribute for a function type shall be applied to a function declarator[190] or to a type specifier that
has a function type. The corresponding attribute is a property of the referred function type[191] . No
attribute argument clause shall be present.
Description
Footnote 190) That is, they appear in the attributes right after the closing parenthesis of the parameter list, independently if the function
type is, for example, used directly to declare a function or if it is used in a pointer to function type.
Footnote 191) If several declarations of the same function or function pointer are visible, regardless whether an attribute is present
3 The main purpose of the function type properties and attributes defined in this clause is to provide
the translator with information about the access of objects by a function such that certain properties
of function calls can be deduced; the properties distinguish read operations (stateless and inde-
pendent) and write operations (effectless, idempotent and reproducible) or a combination of both
(unsequenced). Although semantically attached to a function type, the attributes described are not
part of the prototype of a such annotated function, and redeclarations and conversions that drop
such an attribute are valid and constitute compatible types. Conversely, if a definition that does not
have the asserted property is accessed by a function declaration or a function pointer with a type
that has the attribute, the behavior is undefined[192] .
Footnote 192) That is, the fact that a function has one of these properties is in general not determined by the specification of the
translation unit in which it is found; other translation units and specific run time conditions also condition the possible
assertion of the properties.
4 To allow reordering of calls to functions as they are described here, possible access to objects with a
lifetime that starts before or ends after a call has to be restricted; effects on all objects that are accessed
during a function call are restricted to the same thread as the call and the based-on relation between
pointer parameters and lvalues (<IP_ADDRESS>) models the fact that objects do not change inadvertently
during the call. In the following, an operation is said to be sequenced during a function call if it is
sequenced after the start of the function call[193] and before the call terminates. An object definition
of an object X in a function f escapes if an access to X happens while no call to f is active. An
object is local to a call to a function f if its lifetime starts and ends during the call or if it is defined
by f but does not escape. A function call and an object X synchronize if all accesses to X that are
not sequenced during the call happen before or after the call. Execution state that is described in
the library clause, such as the floating-point environment, conversion state, locale, input/output
streams, external files or errno account as objects; operations that allow to query this state, even
indirectly, account as lvalue conversions, and operations that allow to change this state account as
store operations.
Footnote 193) The initializations of the parameters is sequenced during the function call.
5 A function definition f is stateless if any definition of an object of static or thread storage duration in
f or in a function that is called by f is const but not volatile qualified.
6 An object X is observed by a function call if both synchronize, if X is not local to the call, if X has a
lifetime that starts before the function call and if an access of X is sequenced during the call; the last
value of X, if any, that is stored before the call is said to be the value of X that is observed by the
call. A function pointer value f is independent if for any object X that is observed by some call to f
through an lvalue that is not based on a parameter of the call, then all accesses to X in all calls to
f during the same program execution observe the same value; otherwise if the access is based on
a pointer parameter, there shall be a unique such pointer parameter P such that any access to X
shall be to an lvalue that is based on P . A function definition is independent if the derived function
pointer value is independent.
7 A store operation to an object X that is sequenced during a function call such that both synchronize
is said to be observable if X is not local to the call, if the lifetime of X ends after the call, if the stored
value is different from the value observed by the call, if any, and if it is the last value written before
the termination of the call. An evaluation of a function call[194] is effectless if any store operation
that is sequenced during the call is the modification of an object that synchronizes with the call; if
additionally the operation is observable, there shall be a unique pointer parameter P of the function
such that any access to X shall be to an lvalue that is based on P . A function pointer value f is
effectless if any evaluation of a function call that calls f is effectless. A function definition is effectless
if the derived function pointer value is effectless.
Footnote 194) This considers the evaluation of the function call itself, not the evaluation of a full function call expression. Such an
evaluation is sequenced after all evaluations that determine f and the call arguments, if any, have been performed.
8 An evaluation E is idempotent if a second evaluation of E can be sequenced immediately after the
original one without changing the resulting value, if any, or the observable state of the execution.
at several or just one of the declarators, it is attached to the type of the corresponding function definition, function pointer
object, or function pointer value.
A function pointer value f is idempotent if any evaluation of a function call[195] that calls f is
idempotent. A function definition is idempotent if the derived function pointer value is idempotent.
Footnote 195) This considers the evaluation of the function call itself, not the evaluation of a full function call expression. Such an
evaluated is sequenced after all evaluations that determine f and the call arguments, if any, have been performed.
9 A function is reproducible if it is effectless and idempotent; it is unsequenced if it is stateless, effectless,
idempotent and independent[196] .
Footnote 196) A function call of an unsequenced function can be executed as early as the function pointer value, the values of the
arguments and all objects that are accessible through them, and all values of globally accessible state have been determined,
and it can be executed as late as the arguments and the objects they possibly target are unchanged and as any of its return
value or modified pointed-to arguments are accessed.
10 NOTE The synchronization requirements with respect to any accessed object X for the independence of functions provide
boundaries up to which a function call may safely be reordered without changing the semantics of the program. If X is
const but not volatile qualified the reordering is unconstrained. If it is an object that is conditioned in an initialization
phase, for a single threaded program a synchronization is provided by the sequenced before relation and the reordering
may, in principle, move the call just after the initialization. For a multi-threaded program, synchronization guarantees can be
given by calls to synchronizing functions of the <threads.h> header or by an appropriate call to atomic_thread_fence at
the end of the initialization phase. If a function is known to be independent or effectless, adding restrict qualifications to
the declarations of all pointer parameters does not change the semantics of any call. Similarly, changing the memory order to
memory_order_relaxed for all atomic operations during a call to such a function preserves semantics.
11 NOTE In general the functions provided by the <math.h> header do not have the properties that are defined above; many
of them change the floating-point state or errno when they encounter an error (so they have observable side effects) and the
results of most of them depend on execution wide state such as the rounding direction mode (so they are not independent).
Whether a particular C library function is reproducible or unsequenced additionally often depends on properties of the
implementation, such as implementation-defined behavior for certain error conditions.
Recommended Practice
12 If possible, it is recommended that implementations diagnose if an attribute of this clause is applied
to a function definition that does not have the corresponding property. It is recommended that appli-
cations that assert the independent or effectless properties for functions qualify pointer parameters
with restrict.
Forward references: errors <errno.h> (7.5), floating-point environment <fenv.h> (7.6), localiza-
tion <locale.h> (7.11), mathematics <math.h> (7.12), fences (7.17.4), input/output <stdio.h>
(7.23), threads <threads.h> (7.28), extended multibyte and wide character utilities <wchar.h>
(7.31).
<IP_ADDRESS>.1 [The reproducible type attribute]
1 Description
The reproducible type attribute asserts that a function or pointed-to function with that type is
reproducible.
2 The __has_c_attribute conditional inclusion expression (6.10.1) shall return the value 202207L
when given reproducible as the pp-tokens operand.
3 EXAMPLE 1 The attribute in the following function declaration asserts that two consecutive calls to the function will result
in the same return value. Changes to the abstract state during the call are possible as long as they are not observable, but
no other side effects will occur. Thus the function definition may for example use local objects of static or thread storage
duration to keep track of the arguments for which the function has been called and cache their computed return values.
size_t hash(char const[static 32]) [[reproducible]];
<IP_ADDRESS>.2 [The unsequenced type attribute]
1 Description
The unsequenced type attribute asserts that a function or pointed-to function with that type is
unsequenced.
2 The __has_c_attribute conditional inclusion expression (6.10.1) shall return the value 202207L
when given unsequenced as the pp-tokens operand.
3 NOTE The unsequenced type attribute asserts strong properties for the such typed function, in particular that certain
sequencing requirements for function calls can be relaxed without affecting the state of the abstract machine. Thereby, calls
to such functions are natural candidates for optimization techniques such as common subexpression elimination, local
memoization or lazy evaluation.
4 NOTE A proof of validity of the annotation of a function type with the unsequenced attribute may depend on the property
if a derived function pointer escapes the translation unit or not. For a function with internal linkage where no function
pointer escapes the translation unit, all calling contexts are known and it is possible, in principle, to prove that no control flow
exists such that a library function is called with arguments that trigger an exceptional condition. For a function with external
linkage such a proof may not be possible and the use of such a function then has to ensure that no exceptional condition
results from the provided arguments.
5 NOTE The unsequenced property does not necessarily imply that the function is reentrant or that calls can be executed
concurrently. This is because an unsequenced function can read from and write to objects of static storage duration, as long
as no change is observable after a call terminates.
6 EXAMPLE 1 The attribute in the following function declaration asserts that it doesn’t depend on any modifiable state of the
abstract machine. Calls to the function can be executed out of sequence before the return value is needed and two calls to the
function with the same argument value will result in the same return value.
bool tendency(signed char) [[unsequenced]];
Therefore such a call for a given argument value needs only to be executed once and the returned value can be reused when
appropriate. For example, calls for all possible argument values can be executed during program startup and tabulated.
7 EXAMPLE 2 The attribute in the following function declaration asserts that it doesn’t depend on any modifiable state of
the abstract machine. Within the same thread, calls to the function can be executed out of sequence before the return value
is needed and two calls to the function will result in the same pointer return value. Therefore such a call needs only to be
executed once in a given thread and the returned pointer value can be reused when appropriate. For example, a single
call can be executed during thread startup and the return value p and the value of the object *p of type toto const can be
cached.
typedef struct toto toto;
toto const* toto_zero(void) [[unsequenced]];
8 EXAMPLE 3 The unsequenced property of a function f can be locally asserted within a function g that uses it. For example
the library function sqrt is in generally not unsequenced because a negative argument will raise a domain error and because
the result may depend on the rounding mode. Nevertheless in contexts similar to the following function a user can prove
that it will not be called with invalid arguments, and, that the floating-point environment has the same value for all calls.
#include <math.h>
#include <fenv.h>
inline double distance (double const x[static 2]) [[reproducible]] {
#pragma FP_CONTRACT OFF
#pragma FENV_ROUND FE_TONEAREST
// We assert that sqrt will not be called with invalid arguments
// and the result only depends on the argument value.
extern typeof(sqrt) [[unsequenced]] sqrt;
return sqrt(x[0]*x[0] + x[1]*x[1]);
}
The function distance potentially has the side effect of changing the floating-point environment. Nevertheless the floating
environment is thread local, thus a change to that state outside the function is sequenced with the change within and
additionally the observed value is restored when the function returns. Thus this side effect is not observable for a caller.
Overall the function distance is stateless, effectless and idempotent and in particular it is reproducible as the attribute
indicates. Because the function can be called in a context where the floating-point environment has different state, distance
is not independent and thus it is also not unsequenced. Nevertheless, adding an unsequenced attribute where this is justified
may introduce optimization opportunities.
double g (double y[static 1], double const x[static 2]) {
// We assert that distance will not see different states of the floating
// point environment.
extern double distance (double const x[static 2]) [[unsequenced]];
y[0] = distance(x);
...
return distance(x); // replacement by y[0] is valid
}
6.8 [Statements and blocks]
1 Syntax
statement:
labeled-statement
unlabeled-statement
unlabeled-statement:
expression-statement
attribute-specifier-sequenceopt primary-block
attribute-specifier-sequenceopt jump-statement
primary-block:
compound-statement
selection-statement
iteration-statement
secondary-block:
statement
Semantics
2 A statement specifies an action to be performed. Except as indicated, statements are executed in
sequence. The optional attribute specifier sequence appertains to the respective statement.
3 A block is either a primary block, a secondary block, or the block associated with a function definition;
it allows a set of declarations and statements to be grouped into one syntactic unit. Whenever a
block B appears in the syntax production as part of the definition of an enclosing block A, scopes of
identifiers and lifetimes of objects that are associated with B do not extend to the parts of A that are
outside of B. The initializers of objects that have automatic storage duration, and the variable length
array declarators of ordinary identifiers with block scope, are evaluated and the values are stored in
the objects (the representation of objects without an initializer becomes indeterminate) each time the
declaration is reached in the order of execution, as if it were a statement, and within each declaration
in the order that declarators appear.
4 A full expression is an expression that is not part of another expression, nor part of a declarator
or abstract declarator. There is also an implicit full expression in which the non-constant size
expressions for a variably modified type are evaluated; within that full expression, the evaluation of
different size expressions are unsequenced with respect to one another. There is a sequence point
between the evaluation of a full expression and the evaluation of the next full expression to be
evaluated.
5 NOTE Each of the following is a full expression:
— a full declarator for a variably modified type,
— an initializer that is not part of a compound literal,
— the expression in an expression statement,
— the controlling expression of a selection statement (if or switch),
— the controlling expression of a while or do statement,
— each of the (optional) expressions of a for statement,
— the (optional) expression in a return statement.
While a constant expression satisfies the definition of a full expression, evaluating it does not depend on nor produce any
side effects, so the sequencing implications of being a full expression are not relevant to a constant expression.
Forward references: expression and null statements (6.8.3), selection statements (6.8.4), iteration
statements (6.8.5), the return statement (<IP_ADDRESS>).
6.8.1 [Labeled statements]
1 Syntax
label:
attribute-specifier-sequenceopt identifier :
attribute-specifier-sequenceopt case constant-expression :
attribute-specifier-sequenceopt default :
labeled-statement:
label statement
Constraints
2 A case or default label shall appear only in a switch statement. Further constraints on such labels
are discussed under the switch statement.
3 Label names shall be unique within a function.
Semantics
4 Any statement may be preceded by a prefix that declares an identifier as a label name. The optional
attribute specifier sequence appertains to the label. Labels in themselves do not alter the flow of
control, which continues unimpeded across them.
Forward references: the goto statement (<IP_ADDRESS>), the switch statement (<IP_ADDRESS>) .
6.8.2 [Compound statement]
1 Syntax
compound-statement:
{ block-item-listopt }
block-item-list:
block-item
block-item-list block-item
block-item:
declaration
unlabeled-statement
label
Semantics
2 A compound statement that is a function body together with the parameter type list and the optional
attribute specifier sequence between them forms the block associated with the function definition
in which it appears. Otherwise, it is a block that is different from any other block. A label shall be
translated as if it were followed by a null statement.
6.8.3 [Expression and null statements]
1 Syntax
expression-statement:
expressionopt ;
attribute-specifier-sequence expression ;
Semantics
2 The attribute specifier sequence appertains to the expression. The expression in an expression
statement is evaluated as a void expression for its side effects.[197]
Footnote 197) Such as assignments, and function calls which have side effects.
3 A null statement (consisting of just a semicolon) performs no operations.
4 EXAMPLE 1 If a function call is evaluated as an expression statement for its side effects only, the discarding of its value can
be made explicit by converting the expression to a void expression by means of a cast:
int p(int);
/* ... */
(void)p(0);
5 EXAMPLE 2 In the program fragment
char *s;
/* ... */
while (*s++ != ’\0’)
;
a null statement is used to supply an empty loop body to the iteration statement.
Forward references: iteration statements (6.8.5).
6.8.4 [Selection statements]
1 Syntax
selection-statement:
if ( expression ) secondary-block
if ( expression ) secondary-block else secondary-block
switch ( expression ) secondary-block
Semantics
2 A selection statement selects among a set of secondary blocks depending on the value of a controlling
expression.
<IP_ADDRESS> [The if statement]
1 Constraints
The controlling expression of an if statement shall have scalar type.
Semantics
2 In both forms, the first substatement is executed if the expression compares unequal to 0. In the
else form, the second substatement is executed if the expression compares equal to 0. If the first
substatement is reached via a label, the second substatement is not executed.
3 An else is associated with the lexically nearest preceding if that is allowed by the syntax.
<IP_ADDRESS> [The switch statement]
1 Constraints
The controlling expression of a switch statement shall have integer type.
2 If a switch statement has an associated case or default label within the scope of an identifier with
a variably modified type, the entire switch statement shall be within the scope of that identifier.[198]
Footnote 198) That is, the declaration either precedes the switch statement, or it follows the last case or default label associated with
the switch that is in the block containing the declaration.
3 The expression of each case label shall be an integer constant expression and no two of the case
constant expressions in the same switch statement shall have the same value after conversion.
There may be at most one default label in a switch statement. (Any enclosed switch statement
may have a default label or case constant expressions with values that duplicate case constant
expressions in the enclosing switch statement.)
Semantics
4 A switch statement causes control to jump to, into, or past the statement that is the switch body,
depending on the value of a controlling expression, and on the presence of a default label and the
values of any case labels on or in the switch body. A case or default label is accessible only within
the closest enclosing switch statement.
5 The integer promotions are performed on the controlling expression. The constant expression in
each case label is converted to the promoted type of the controlling expression. If a converted value
matches that of the promoted controlling expression, control jumps to the statement following the
matched case label. Otherwise, if there is a default label, control jumps to the statement following
the default label. If no converted case constant expression matches and there is no default label,
no part of the switch body is executed.
Implementation limits
6 As discussed in <IP_ADDRESS>, the implementation may limit the number of case values in a switch
statement.
7 EXAMPLE In the artificial program fragment
switch (expr)
{
int i = 4;
f(i);
case 0:
i = 17;
/* falls through into default code */
default:
printf("%d\n", i);
}
the object whose identifier is i exists with automatic storage duration (within the block) but is never initialized, and thus if
the controlling expression has a nonzero value, the call to the printf function will access an object with an indeterminate
representation. Similarly, the call to the function f cannot be reached.
6.8.5 [Iteration statements]
1 Syntax
iteration-statement:
while ( expression ) secondary-block
do secondary-block while ( expression ) ;
for ( expressionopt ; expressionopt ; expressionopt ) secondary-block
for ( declaration expressionopt ; expressionopt ) secondary-block
Constraints
2 The controlling expression of an iteration statement shall have scalar type.
3 The declaration part of a for statement shall only declare identifiers for objects having storage class
auto or register.
Semantics
4 An iteration statement causes a secondary block called the loop body to be executed repeatedly until
the controlling expression compares equal to 0. The repetition occurs regardless of whether the loop
body is entered from the iteration statement or by a jump[199] .
Footnote 199) Code jumped over is not executed. In particular, the controlling expression of a for or while statement is not evaluated
before entering the loop body, nor is clause-1 of a for statement.
5 An iteration statement may be assumed by the implementation to terminate if its controlling
expression is not a constant expression[200] , and none of the following operations are performed in its
body, controlling expression or (in the case of a for statement) its expression-3201) :
— input/output operations
— accessing a volatile object
— synchronization or atomic operations.
Footnote 200) An omitted controlling expression is replaced by a nonzero constant, which is a constant expression.
<IP_ADDRESS> [The while statement]
1 The evaluation of the controlling expression takes place before each execution of the loop body.
<IP_ADDRESS> [The do statement]
1 The evaluation of the controlling expression takes place after each execution of the loop body.
<IP_ADDRESS> [The for statement]
1 The statement
for (clause-1; expression-2; expression-3) statement
behaves as follows: The expression expression-2 is the controlling expression that is evaluated before
each execution of the loop body. The expression expression-3 is evaluated as a void expression after
each execution of the loop body. If clause-1 is a declaration, the scope of any identifiers it declares
is the remainder of the declaration and the entire loop, including the other two expressions; it is
reached in the order of execution before the first evaluation of the controlling expression. If clause-1
is an expression, it is evaluated as a void expression before the first evaluation of the controlling
expression.[202]
Footnote 202) Thus, clause-1 specifies initialization for the loop, possibly declaring one or more variables for use in the loop; the
controlling expression, expression-2, specifies an evaluation made before each iteration, such that execution of the loop
continues until the expression compares equal to 0; and expression-3 specifies an operation (such as incrementing) that is
performed after each iteration.
2 Both clause-1 and expression-3 can be omitted. An omitted expression-2 is replaced by a nonzero
constant.
6.8.6 [Jump statements]
1 Syntax
jump-statement:
goto identifier ;
continue ;
break ;
return expressionopt ;
Semantics
2 A jump statement causes an unconditional jump to another place.
<IP_ADDRESS> [The goto statement]
1 Constraints
The identifier in a goto statement shall name a label located somewhere in the enclosing function. A
goto statement shall not jump from outside the scope of an identifier having a variably modified
type to inside the scope of that identifier.
Semantics
2 A goto statement causes an unconditional jump to the statement prefixed by the named label in the
enclosing function.
3 EXAMPLE 1 It is sometimes convenient to jump into the middle of a complicated set of statements. The following outline
presents one possible approach to a problem based on these three assumptions:
1. The general initialization code accesses objects only visible to the current function.
2. The general initialization code is too large to warrant duplication.
3. The code to determine the next operation is at the head of the loop. (To allow it to be reached by continue statements,
for example.)
/* ... */
goto first_time;
for (;;) {
// determine next operation
/* ... */
if (need to reinitialize) {
// reinitialize-only code
/* ... */
first_time:
// general initialization code
/* ... */
continue;
}
// handle other operations
/* ... */
}
4 EXAMPLE 2 A goto statement is not allowed to jump past any declarations of objects with variably modified types. A jump
within the scope, however, is permitted.
goto lab3; // invalid: going INTO scope of VLA.
{
double a[n];
a[j] = 4.4;
lab3:
a[j] = 3.3;
goto lab4; // valid: going WITHIN scope of VLA.
a[j] = 5.5;
lab4:
a[j] = 6.6;
}
goto lab4; // invalid: going INTO scope of VLA.
<IP_ADDRESS> [The continue statement]
1 Constraints
A continue statement shall appear only in or as a loop body.
Semantics
2 A continue statement causes a jump to the loop-continuation portion of the smallest enclosing
iteration statement; that is, to the end of the loop body. More precisely, in each of the statements
while (/* ... */) { do { for (/* ... */) {
/* ... */ /* ... */ /* ... */
continue; continue; continue;
/* ... */ /* ... */ /* ... */
contin: contin: contin:
} } while (/* ... */); }
unless the continue statement shown is in an enclosed iteration statement (in which case it is
interpreted within that statement), it is equivalent to goto contin;.[203]
Footnote 203) Following the contin: label in the 2nd example is a null statement. The null statement in the first and third example is
implied by the label (6.8.2).
<IP_ADDRESS> [The break statement]
1 Constraints
A break statement shall appear only in or as a switch body or loop body.
Semantics
2 A break statement terminates execution of the smallest enclosing switch or iteration statement.
<IP_ADDRESS> [The return statement]
1 Constraints
A return statement with an expression shall not appear in a function whose return type is void. A
return statement without an expression shall only appear in a function whose return type is void .
Semantics
2 A return statement terminates execution of the current function and returns control to its caller. A
function may have any number of return statements.
3 If a return statement with an expression is executed, the value of the expression is returned to the
caller as the value of the function call expression. If the expression has a type different from the
return type of the function in which it appears, the value is converted as if by assignment to an
object having the return type of the function.[204]
Footnote 204) The return statement is not an assignment. The overlap restriction of <IP_ADDRESS> does not apply to the case of function
return. The representation of floating-point values can have wider range or precision than implied by the type; a cast can be
used to remove this extra range and precision.
4 EXAMPLE In:
struct s { double i; } f(void);
union {
struct {
int f1;
struct s f2;
} u1;
struct {
struct s f3;
int f4;
} u2;
} g;
struct s f(void)
{
return g.u1.f2;
}
/* ... */
g.u2.f3 = f();
there is no undefined behavior, although there would be if the assignment were done directly (without using a function call
to fetch the value).
6.9 [External definitions]
1 Syntax
translation-unit:
external-declaration
translation-unit external-declaration
external-declaration:
function-definition
declaration
Constraints
2 The storage-class specifier register shall not appear in the declaration specifiers in an external
declaration.
3 There shall be no more than one external definition for each identifier declared with internal linkage
in a translation unit. Moreover, if an identifier declared with internal linkage is used in an expression
there shall be exactly one external definition for the identifier in the translation unit, unless it is:
— part of the operand of a sizeof operator whose result is an integer constant;
— part of the operand of an alignof operator whose result is an integer constant;
— or, part of the operand of any typeof operator whose result is not a variably modified type.
Semantics
4 As discussed in <IP_ADDRESS>, the unit of program text after preprocessing is a translation unit, which
consists of a sequence of external declarations. These are described as "external" because they
appear outside any function (and hence have file scope). As discussed in 6.7, a declaration that also
causes storage to be reserved for an object or a function named by the identifier is a definition.
5 An external definition is an external declaration that is also a definition of a function (other than an
inline definition) or an object. If an identifier declared with external linkage is used in an expression
(other than as part of the operand of a typeof operator whose result is not a variably modified type,
or a sizeof or alignof operator whose result is an integer constant expression), somewhere in the
entire program there shall be exactly one external definition for the identifier; otherwise, there shall
be no more than one[205] .
Footnote 205) Thus, if an identifier declared with external linkage is not used in an expression, there need be no external definition for
it.
6.9.1 [Function definitions]
1 Syntax
function-definition:
attribute-specifier-sequenceopt declaration-specifiers declarator function-body
function-body:
compound-statement
Constraints
2 The identifier declared in a function definition (which is the name of the function) shall have a
function type, as specified by the declarator portion of the function definition.
3 The return type of a function shall be void or a complete object type other than array type.
4 The storage-class specifier, if any, in the declaration specifiers shall be either extern or static.
5 If the parameter list consists of a single parameter of type void, the parameter declarator shall not
include an identifier.
Semantics
6 The optional attribute specifier sequence in a function definition appertains to the function.
7 The declarator in a function definition specifies the name of the function being defined and the
types (and optionally the names) of all the parameters; the declarator also serves as a function
prototype for later calls to the same function in the same translation unit. The type of each parameter
is adjusted as described in <IP_ADDRESS>.
8 If a function that accepts a variable number of arguments is defined without a parameter type list
that ends with the ellipsis notation, the behavior is undefined.
9 The parameter type list, the attribute specifier sequence of the declarator that follows the parameter
type list, and the compound statement of the function body form a single block[206] . Each parameter
has automatic storage duration; its identifier, if any[207] , is an lvalue[208] . The layout of the storage for
parameters is unspecified.
Footnote 206) The visibility scope of a parameter in a function definition starts when its declaration is completed, extends to following
parameter declarations, to possible attributes that follow the parameter type list, and then to the entire function body. The
lifetime of each instance of a parameter starts when the declaration is evaluated starting a call and ends when that call
terminates.
Footnote 207) A parameter that has no declared name is inaccessible within the function body.
Footnote 208) A parameter identifier cannot be redeclared in the function body except in an enclosed block.
10 On entry to the function, the size expressions of each variably modified parameter are evaluated
and the value of each argument expression is converted to the type of the corresponding parameter
as if by assignment. (Array expressions and function designators as arguments were converted to
pointers before the call.)
11 After all parameters have been assigned, the compound statement of the function body is executed.
12 Unless otherwise specified, if the } that terminates the function body is reached, and the value of the
function call is used by the caller, the behavior is undefined.
13 NOTE In a function definition, the type of the function and its prototype cannot be inherited from a typedef:
typedef int F(void); // type F is "function with no parameters
// returning int"
F f, g; // f and g both have type compatible with F
F f { /* ... */ } // WRONG: syntax/constraint error
F g() { /* ... */ } // WRONG: declares that g returns a function
int f(void) { /* ... */ } // RIGHT: f has type compatible with F
int g() { /* ... */ } // RIGHT: g has type compatible with F
F *e(void) { /* ... */ } // e returns a pointer to a function
F *((e))(void) { /* ... */ } // same: parentheses irrelevant
int (*fp)(void); // fp points to a function that has type F
F *Fp; // Fp points to a function that has type F
14 EXAMPLE 1 In the following:
extern int max(int a, int b)
{
return a > b ? a: b;
}
extern is the storage-class specifier and int is the type specifier; max(int a, int b) is the function declarator; and
{ return a > b ? a: b; }
is the function body.
15 EXAMPLE 2 To pass one function to another, one might say
int f(void);
/* ... */
g(f);
Then the definition of g might read
void g(int (*funcp)(void))
{
/* ... */
(*funcp)(); /* or funcp(); ...*/
}
or, equivalently,
void g(int func(void))
{
/* ... */
func(); /* or (*func)(); ...*/
}
6.9.2 [External object definitions]
1 Semantics
If the declaration of an identifier for an object has file scope and an initializer, the declaration is an
external definition for the identifier.
2 A declaration of an identifier for an object that has file scope without an initializer, and without a
storage-class specifier or with the storage-class specifier static, constitutes a tentative definition. If a
translation unit contains one or more tentative definitions for an identifier, and the translation unit
contains no external definition for that identifier, then the behavior is exactly as if the translation
unit contains a file scope declaration of that identifier, with the composite type as of the end of the
translation unit, with an initializer equal to { 0 } .
3 If the declaration of an identifier for an object is a tentative definition and has internal linkage, the
declared type shall not be an incomplete type.
4 EXAMPLE 1
int i1 = 1; // definition, external linkage
static int i2 = 2; // definition, internal linkage
extern int i3 = 3; // definition, external linkage
int i4; // tentative definition, external linkage
static int i5; // tentative definition, internal linkage
int i1; // valid tentative definition, refers to previous
int i2; // 6.2.2 renders undefined, linkage disagreement
int i3; // valid tentative definition, refers to previous
int i4; // valid tentative definition, refers to previous
int i5; // 6.2.2 renders undefined, linkage disagreement
extern int i1; // refers to previous, whose linkage is external
extern int i2; // refers to previous, whose linkage is internal
extern int i3; // refers to previous, whose linkage is external
extern int i4; // refers to previous, whose linkage is external
extern int i5; // refers to previous, whose linkage is internal
5 EXAMPLE 2 If at the end of the translation unit containing
int i[];
the array i still has incomplete type, the implicit initializer causes it to have one element, which is set to zero on program
startup.
6.10 [Preprocessing directives]
1 Syntax
preprocessing-file:
groupopt
group:
group-part
group group-part
group-part:
if-section
control-line
text-line
# non-directive
if-section:
if-group elif-groupsopt else-groupopt endif-line
if-group:
# if constant-expression new-line groupopt
# ifdef identifier new-line groupopt
# ifndef identifier new-line groupopt
elif-groups:
elif-group
elif-groups elif-group
elif-group:
# elif constant-expression new-line groupopt
# elifdef identifier new-line groupopt
# elifndef identifier new-line groupopt
else-group:
# else new-line groupopt
endif-line:
# endif new-line
control-line:
# include pp-tokens new-line
# embed pp-tokens new-line
# define identifier replacement-list new-line
# define identifier lparen identifier-listopt ) replacement-list new-line
# define identifier lparen ... ) replacement-list new-line
# define identifier lparen identifier-list , ... ) replacement-list new-line
# undef identifier new-line
# line pp-tokens new-line
# error pp-tokensopt new-line
# warning pp-tokensopt new-line
# pragma pp-tokensopt new-line
# new-line
text-line:
pp-tokensopt new-line
non-directive:
pp-tokens new-line
lparen:
a ( character not immediately preceded by white space
replacement-list:
pp-tokensopt
pp-tokens:
preprocessing-token
pp-tokens preprocessing-token
new-line:
the new-line character
identifier-list:
identifier
identifier-list , identifier
pp-parameter:
pp-parameter-name pp-parameter-clauseopt
pp-parameter-name:
pp-standard-parameter
pp-prefixed-parameter
pp-standard-parameter:
identifier
pp-prefixed-parameter:
identifier :: identifier
pp-parameter-clause:
( pp-balanced-token-sequenceopt )
pp-balanced-token-sequence:
pp-balanced-token
pp-balanced-token-sequence pp-balanced-token
pp-balanced-token:
( pp-balanced-token-sequenceopt )
[ pp-balanced-token-sequenceopt ]
{ pp-balanced-token-sequenceopt }
any pp-token other than a parenthesis, a bracket, or a brace
embed-parameter-sequence:
pp-parameter
embed-parameter-sequence pp-parameter
Description
2 A preprocessing directive consists of a sequence of preprocessing tokens that satisfies the following
constraints: The first token in the sequence is a # preprocessing token that (at the start of translation
phase 4) is either the first character in the source file (optionally after white space containing no
new-line characters) or that follows white space containing at least one new-line character. The last
token in the sequence is the first new-line character that follows the first token in the sequence. [209]
A new-line character ends the preprocessing directive even if it occurs within what would otherwise
be an invocation of a function-like macro.
Footnote 209) Thus, preprocessing directives are commonly called "lines". These "lines" have no other syntactic significance, as all
white space is equivalent except in certain situations during preprocessing (see the # character string literal creation operator
3 A text line shall not begin with a # preprocessing token. A non-directive shall not begin with any of
the directive names appearing in the syntax.
4 Some preprocessing directives take additional information by the use of preprocessor parameters.
A preprocessing parameter (pp-parameter) shall be either a preprocessor prefixed parameter (identified
by a pp-prefixed-parameter, for implementation-defined preprocessor parameters) or a preprocessor
standard parameter (identified with a pp-standard-parameter, for pp-parameters specified by this
document).
5 In all aspects, a preprocessor standard parameter specified by this document as an identifier pp_param
and an identifier of the form __pp_param__ shall behave the same when used as a preprocessor
parameter, except for the spelling.
6 EXAMPLE 1 Thus, the preprocessor parameters on the two binary resource inclusion directives (<IP_ADDRESS>):
#embed "boop.h" limit(5)
#embed "boop.h" __limit__(5)
behave the same, and can be freely interchanged. Implementations are encouraged to behave similarly for preprocessor
parameters (including preprocessor prefixed parameters) they provide.
7 When in a group that is skipped (6.10.1), the directive syntax is relaxed to allow any sequence of
preprocessing tokens to occur between the directive name and the following new-line character.
Constraints
8 The only white-space characters that shall appear between preprocessing tokens within a prepro-
cessing directive (from just after the introducing # preprocessing token through just before the
terminating new-line character) are space and horizontal-tab (including spaces that have replaced
comments or possibly other white-space characters in translation phase 3).
9 A preprocessor parameter shall be either a preprocessor standard parameter, or an implementation-
defined preprocessor prefixed parameter[210] .
Semantics
Footnote 210) An unrecognized preprocessor prefixed parameter is a constraint violation, except within has_embed expressions (6.10.1).
10 The implementation can process and skip sections of source files conditionally, include other source
files, and replace macros. These capabilities are called preprocessing, because conceptually they occur
before translation of the resulting translation unit.
11 The preprocessing tokens within a preprocessing directive are not subject to macro expansion unless
otherwise stated.
12 EXAMPLE In:
#define EMPTY
EMPTY # include <file.h>
the sequence of preprocessing tokens on the second line is not a preprocessing directive, because it does not begin with a # at
the start of translation phase 4, even though it will do so after the macro EMPTY has been replaced.
13 The execution of a non-directive preprocessing directive results in undefined behavior.
6.10.1 [Conditional inclusion]
1 Syntax
defined-macro-expression:
defined identifier
defined ( identifier )
h-preprocessing-token:
any preprocessing-token other than >
in <IP_ADDRESS>, for example).
h-pp-tokens:
h-preprocessing-token
h-pp-tokens h-preprocessing-token
header-name-tokens:
string-literal
< h-pp-tokens >
has-include-expression:
__has_include ( header-name )
__has_include ( header-name-tokens )
has-embed-expression:
__has_embed ( header-name embed-parameter-sequenceopt )
__has_embed ( header-name-tokens pp-balanced-token-sequenceopt )
has-c-attribute-express:
__has_c_attribute ( pp-tokens )
Constraints
2 The expression that controls conditional inclusion shall be an integer constant expression except that:
identifiers (including those lexically identical to keywords) are interpreted as described below[211]
and it may contain zero or more defined macro expressions, has_include expressions, has_embed
expressions, and/or has_c_attribute expressions as unary operator expressions.
Footnote 211) Because the controlling constant expression is evaluated during translation phase 4, all identifiers either are or are not
macro names — there simply are no keywords, enumeration constants, etc.
3 A defined macro expression evaluates to 1 if the identifier is currently defined as a macro name (that
is, if it is predefined or if it has been the subject of a #define preprocessing directive without an
intervening #undef directive with the same subject identifier), 0 if it is not.
4 The second form of the has_include expression and has_embed expression is considered only if the
first form does not match, in which case the preprocessing tokens are processed just as in normal
text.
5 The header or source file identified by the parenthesized preprocessing token sequence in each
contained has_include expression is searched for as if that preprocessing token were the pp-tokens
in a #include directive, except that no further macro expansion is performed. Such a directive shall
satisfy the syntactic requirements of a #include directive. The has_include expression evaluates to
1 if the search for the source file succeeds, and to 0 if the search fails.
6 The resource (<IP_ADDRESS>) identified by the header-name preprocessing token sequence in each contained
has_embed expression is searched for as if those preprocessing token were the pp-tokens in a #embed
directive, except that no further macro expansion is performed. Such a directive shall satisfy the
syntactic requirements of a #embed directive. The has_embed expression evaluates to:
— 0 if the search fails or if any of the embed parameters in the embed parameter sequence
specified are not supported by the implementation for the #embed directive; or,
— 1 if the search for the resource succeeds and all embed parameters in the embed parameter
sequence specified are supported by the implementation for the #embed directive and the
resource is not empty; or,
— 2 if the search for the resource succeeds and all embed parameters in the embed parameter
sequence specified are supported by the implementation for the #embed directive and the
resource is empty.
7 NOTE Unrecognized preprocessor prefixed parameters in has_embed expressions is not a constraint violation and instead
causes the expression to be evaluate to 0, as specified above.
8 Each has_c_attribute expression is replaced by a nonzero pp-number matching the form of an integer
constant if the implementation supports an attribute with the name specified by interpreting the
pp-tokens as an attribute token, and by 0 otherwise. The pp-tokens shall match the form of an
attribute token.
9 Each preprocessing token that remains (in the list of preprocessing tokens that will become the
controlling expression) after all macro replacements have occurred shall be in the lexical form of a
token (6.4).
Semantics
10 The #ifdef, #ifndef, #elifdef, and #elifndef, and the defined conditional inclusion operator,
shall treat __has_include and __has_c_attribute as if they were the name of defined macros.
The identifiers __has_include , __has_embed , and __has_c_attribute shall not appear in any
context not mentioned in this subclause.
11 Preprocessing directives of the forms
# if constant-expression new-line groupopt
# elif constant-expression new-line groupopt
check whether the controlling constant expression evaluates to nonzero.
12 Prior to evaluation, macro invocations in the list of preprocessing tokens that will become the control-
ling constant expression are replaced (except for those macro names modified by the defined unary
operator), just as in normal text. If the token defined is generated as a result of this replacement
process or use of the defined unary operator does not match one of the two specified forms prior to
macro replacement, the behavior is undefined. After all replacements due to macro expansion and
evaluations of defined macro expressions, has_include expressions, and has_c_attribute expressions
have been performed, all remaining identifiers other than true (including those lexically identical
to keywords such as false) are replaced with the pp-number 0, true is replaced with pp-number
1 , and then each preprocessing token is converted into a token. The resulting tokens compose the
controlling constant expression which is evaluated according to the rules of 6.6. For the purposes of
this token conversion and evaluation, all signed integer types and all unsigned integer types act as
if they have the same representation as, respectively, the types intmax_t and uintmax_t defined
in the header <stdint.h>. [212] This includes interpreting character constants, which may involve
converting escape sequences into execution character set members. Whether the numeric value for
these character constants matches the value obtained when an identical character constant occurs in
an expression (other than within a #if or #elif directive) is implementation-defined[213] .
Also, whether a single-character character constant may have a negative value is implementation-
defined.
Footnote 212) Thus, on an implementation where INT_MAX is 0x7FFF and UINT_MAX is 0xFFFF, the constant 0x8000 is signed and
positive within a #if expression even though it would be unsigned in translation phase 7.
Footnote 213) Thus, the constant expression in the following #if directive and if statement is not guaranteed to evaluate to the same
value in these two contexts.
#if ’z’ - ’a’ == 25
if (’z’ - ’a’ == 25)
13 Preprocessing directives of the forms
# ifdef identifier new-line groupopt
# ifndef identifier new-line groupopt
# elifdef identifier new-line groupopt
# elifndef identifier new-line groupopt
check whether the identifier is or is not currently defined as a macro name. Their conditions
are equivalent to #if defined identifier, #if !defined identifier, #elif defined identifier, and
#elif !defined identifier respectively.
14 Each directive’s condition is checked in order. If it evaluates to false (zero), the group that it
controls is skipped: directives are processed only through the name that determines the directive
in order to keep track of the level of nested conditionals; the rest of the directives’ preprocessing
tokens are ignored, as are the other preprocessing tokens in the group. Only the first group whose
control condition evaluates to true (nonzero) is processed; any following groups are skipped and
their controlling directives are processed as if they were in a group that is skipped. If none of the
conditions evaluates to true, and there is a #else directive, the group controlled by the #else is
processed; lacking a #else directive, all the groups until the #endif are skipped. [214]
Footnote 214) As indicated by the syntax, no preprocessing tokens are allowed to follow a #else or #endif directive before the
terminating new-line character. However, comments can appear anywhere in a source file, including within a preprocessing
directive.
15 EXAMPLE This demonstrates a way to include a header file only if it is available.
#if __has_include(<optional.h>)
# include <optional.h>
# define have_optional 1
#elif __has_include(<experimental/optional.h>)
# include <experimental/optional.h>
# define have_optional 1
# define have_experimental_optional 1
#endif
#ifndef have_optional
# define have_optional 0
#endif
16 EXAMPLE
/* Fallback for compilers not yet implementing this feature. */
#ifndef __has_c_attribute
#define __has_c_attribute(x) 0
#endif /* __has_c_attribute */
#if __has_c_attribute(fallthrough)
/* Standard attribute is available, use it. */
#define FALLTHROUGH [[fallthrough]]
#elif __has_c_attribute(vendor::fallthrough)
/* Vendor attribute is available, use it. */
#define FALLTHROUGH [[vendor::fallthrough]]
#else
/* Fallback implementation. */
#define FALLTHROUGH
#endif
17 EXAMPLE
#ifdef __STDC__
#define TITLE "ISO C Compilation"
#elifndef __cplusplus
#define TITLE "Non-ISO C Compilation"
#else
/* C++ */
#define TITLE "C++ Compilation"
#endif
18 EXAMPLE 1 A combination of __FILE__ (<IP_ADDRESS>) and __has_embed could be used to check for support of specific implemen-
tation extensions for the #embed (<IP_ADDRESS>) directive’s parameters.
#if __has_embed(__FILE__ ext::token(0xB055))
#define DESCRIPTION "Supports extended token embed"
#else
#define DESCRIPTION "Does not support extended token embed"
#endif
19 EXAMPLE 2 The below snippet uses __has_embed to check for support of a specific implementation-defined embed
parameter, and otherwise uses standard behavior to produce the same effect.
void parse_into_s(short* ptr, unsigned char* ptr_bytes, unsigned long long size);
int main () {
#if __has_embed ("bits.bin" ds9000::element_type(short))
/* Implementation extension: create short integers from the */
/* translation environment resource into */
/* a sequence of integer constants */
short meow[] = {
#embed "bits.bin" ds9000::element_type(short)
};
#elif __has_embed ("bits.bin")
/* no support for implementation-specific */
/* ds9000::element_type(short) parameter */
const unsigned char meow_bytes[] = {
#embed "bits.bin"
};
short meow[sizeof(meow_bytes) / sizeof(short)] = {};
/* parse meow_bytes into short values by-hand! */
parse_into_s(meow, meow_bytes, sizeof(meow_bytes));
#else
#error "cannot find bits.bin resource"
#endif
return (int)(meow[0] + meow[(sizeof(meow) / sizeof(*meow)) - 1]);
}
20 EXAMPLE 3 This resource is considered empty due to the limit(0) embed parameter, always, including in __has_embed
expressions.
int main () {
#if __has_embed(</owo/uwurandom> limit(0)) == 2
// if </owo/uwurandom> exits, this
// token sequence is always taken.
return 0;
#else
// the resource does not exist
#error "The resource does not exist"
#endif
}
Forward references: macro replacement (6.10.4), source file inclusion (6.10.2), mandatory macros
(<IP_ADDRESS>), largest integer types (<IP_ADDRESS>).
6.10.2 [Source file inclusion]
1 Constraints
A #include directive shall identify a header or source file that can be processed by the implementa-
tion.
Semantics
2 A preprocessing directive of the form
# include < h-char-sequence > new-line
searches a sequence of implementation-defined places for a header identified uniquely by the
specified sequence between the < and > delimiters, and causes the replacement of that directive
by the entire contents of the header. How the places are specified or the header identified is
implementation-defined.
3 A preprocessing directive of the form
# include " q-char-sequence " new-line
causes the replacement of that directive by the entire contents of the source file identified by
the specified sequence between the " delimiters. The named source file is searched for in an
implementation-defined manner. If this search is not supported, or if the search fails, the directive is
reprocessed as if it read
# include < h-char-sequence > new-line
with the identical contained sequence (including > characters, if any) from the original directive.
4 A preprocessing directive of the form
# include pp-tokens new-line
(that does not match one of the two previous forms) is permitted. The preprocessing tokens after
include in the directive are processed just as in normal text. (Each identifier currently defined as a
macro name is replaced by its replacement list of preprocessing tokens.) The directive resulting after
all replacements shall match one of the two previous forms.[215] The method by which a sequence
of preprocessing tokens between a < and a > preprocessing token pair or a pair of " characters is
combined into a single header name preprocessing token is implementation-defined.
Footnote 215) Note that adjacent string literals are not concatenated into a single string literal (see the translation phases in <IP_ADDRESS>);
thus, an expansion that results in two string literals is an invalid directive.
5 The implementation shall provide unique mappings for sequences consisting of one or more nondig-
its or digits (<IP_ADDRESS>) followed by a period (.) and a single nondigit. The first character shall not be a
digit. The implementation may ignore distinctions of alphabetical case and restrict the mapping to
eight significant characters before the period.
6 A #include preprocessing directive may appear in a source file that has been read because of a
#include directive in another file, up to an implementation-defined nesting limit (see <IP_ADDRESS>).
7 EXAMPLE 1 The most common uses of #include preprocessing directives are as in the following:
#include <stdio.h>
#include "myprog.h"
8 EXAMPLE 2 This illustrates macro-replaced #include directives:
#if VERSION == 1
#define INCFILE "vers1.h"
#elif VERSION == 2
#define INCFILE "vers2.h" // and so on
#else
#define INCFILE "versN.h"
#endif
#include INCFILE
Forward references: macro replacement (6.10.4).
6.10.3 [Binary resource inclusion]
<IP_ADDRESS> [#embed preprocessing directive]
1 Description
A resource is a source of data accessible from the translation environment. An embed parameter is a
single preprocessor parameter in the embed parameter sequence. It has an implementation resource
width, which is the implementation-defined size in bits of the located resource. It also has a resource
width, which is either:
— the number of bits as computed from the optionally-provided limit embed parameter (??), if
present; or,
— the implementation resource width.
2 An embed parameter sequence is a whitespace-delimited list of preprocessor parameters which may
modify the result of the replacement for the #embed preprocessing directive.
Constraints
3 An #embed directive shall identify a resource that can be processed by the implementation as a
binary data sequence given the provided embed parameters.
4 Embed parameters not specified in this document shall be implementation-defined. Implementation-
defined embed parameters may change the below-defined semantics of the directive; otherwise,
#embed directives which do not contain implementation-defined embed parameters shall behave as
described in this document.
5 A resource is considered empty when its resource width is zero.
6 Let embed element width be either:
— an integer constant expression greater than zero determined by an implementation-defined
embed parameter; or,
— CHAR_BIT (<IP_ADDRESS>.1).
The result of (resource width) % (embed element width) shall be zero[216] .
Semantics
Footnote 216) This constraint helps ensure data is neither filled with padding values nor truncated in a given environment, and helps
ensure the data is portable with respect to usages of memcpy (<IP_ADDRESS>) with character type arrays initialized from the data.
7 The expansion of a #embed directive is a token sequence formed from the list of integer constant
expressions described below. The group of tokens for each integer constant expression in the list
is separated in the token sequence from the group of tokens for the previous integer constant
expression in the list by a comma. The sequence neither begins nor ends in a comma. If the list of
integer constant expressions is empty, the token sequence is empty. The directive is replaced by its
expansion and, with the presence of certain embed parameters, additional or replacement token
sequences.
8 A preprocessing directive of the form
# embed < h-char-sequence > embed-parameter-sequenceopt new-line
searches a sequence of implementation-defined places for a resource identified uniquely by the spec-
ified sequence between the < and > . The search for the named resource is done in an implementation-
defined manner.
9 A preprocessing directive of the form
# embed " q-char-sequence " embed-parameter-sequenceopt new-line
searches a sequence of implementation-defined places for a resource identified uniquely by the
specified sequence between the " delimiters. The search for the named resource is done in an
implementation-defined manner. If this search is not supported, or if the search fails, the directive is
reprocessed as if it read
# embed < h-char-sequence > embed-parameter-sequenceopt new-line
with the identical contained q-char-sequence (including > characters, if any) from the original
directive.
10 Either form of the #embed directive specified previously behave as specified below. The values of the
integer constant expressions in the expanded sequence is determined by an implementation-defined
mapping of the resource’s data. Each integer constant expression’s value is in the range from 0 to
(2embed element width ) − 1, inclusive[217] . If the list of integer constant expressions:
— is used to initialize an array of a type compatible with unsigned char, or compatible with
char if char cannot hold negative values; or,
— the embed element width is equal to CHAR_BIT (??env-consider-characteristics-of-integer-
types-limits-h)),
then the contents of the initialized elements of the array are as-if the resource’s binary data is fread
(<IP_ADDRESS>) into the array at translation time.
Footnote 217) For example, an embed element width of 8 will yield a range of values from 0 to 255, inclusive.
11 A preprocessing directive of the form
# embed pp-tokens new-line
(that does not match one of the two previous forms) is permitted. The preprocessing tokens after
embed in the directive are processed just as in normal text. (Each identifier currently defined as a
macro name is replaced by its replacement list of preprocessing tokens.) The directive resulting after
all replacements shall match one of the two previous forms[218] . The method by which a sequence
of preprocessing tokens between a < and a > preprocessing token pair or a pair of " characters is
combined into a single resource name preprocessing token is implementation-defined.
Footnote 218) Note that adjacent string literals are not concatenated into a single string literal (see the translation phases in <IP_ADDRESS>);
thus, an expansion that results in two string literals is an invalid directive.
12 An embed parameter with a preprocessor parameter token that is one of the following is a standard
embed parameter:
limit prefix suffix if_empty
The significance of these standard embed parameters is specified below.
Recommended practice
13 The #embed directive is meant to translate binary data in resources to sequence of integer constant
expressions in a way that preserves the value of the resource’s bit stream where possible.
14 A mechanism similar to, but distinct from, the implementation-defined search paths used for source
file inclusion (6.10.2) is encouraged.
15 Implementations should take into account translation-time bit and byte orders as well as execution
time bit and byte orders to more appropriately represent the resource’s binary data from the directive.
This maximizes the chance that, if the resource referenced at translation time through the #embed
directive is the same one accessed through execution-time means, the data that is e.g. fread or
similar into contiguous storage will compare bit-for-bit equal to an array of character type initialized
from an #embed directive’s expanded contents.
16 EXAMPLE 1 Placing a small image resource.
#include <stddef.h>
void have_you_any_wool(const unsigned char*, size_t);
int main (int, char*[]) {
static const unsigned char baa_baa[] = {
#embed "black_sheep.ico"
};
have_you_any_wool(baa_baa, sizeof(baa_baa));
return 0;
}
17 EXAMPLE 2 This snippet:
int main (int, char*[]) {
static const unsigned char coefficients[] = {
#embed "only_8_bits.bin" // potential constraint violation
};
return 0;
}
may violate the constraint that (resource width) % (embed element width) must be 0. The 8 bits might not be evenly
divisible by the embed element width (e.g., on a system where CHAR_BIT is 16). Issuing a diagnostic in this case may aid in
portability by calling attention to potentially incompatible expectations between implementations and their resources.
18 EXAMPLE 3 Initialization of non-arrays.
int main () {
/* Braces may be kept or elided as per normal initialization rules */
int i = {
#embed "i.dat"
}; /* i value is [0, 2^(embed element width)) first entry */
int i2 =
#embed "i.dat"
; /* valid if i.dat produces 1 value,
i2 value is [0, 2^(embed element width)) */
struct s {
double a, b, c;
struct { double e, f, g; };
double h, i, j;
};
struct s x = {
/* initializes each element in
order according to initialization rules with
comma-separated list of integer constant expressions
inside of braces */
#embed "s.dat"
};
return 0;
}
Non-array types can still be initialized since the directive produces a comma-delimited lists of integer constant expressions, a
single integer constant expression, or nothing.
19 EXAMPLE 4 Equivalency of bit sequence and bit order between a translation-time read and an execution-time read of the
same resource/file.
#include <string.h>
#include <stddef.h>
#include <stdio.h>
int main() {
static const unsigned char embed_data[] = {
#embed <data.dat>
};
const size_t f_size = sizeof(embed_data);
unsigned char f_data[f_size];
FILE* f_source = fopen("data.dat", "rb");
if (f_source == NULL);
return 1;
char* f_ptr = (char*)&f_data[0];
if (fread(f_ptr, 1, f_size, f_source) != f_size) {
fclose(f_source);
return 1;
}
fclose(f_source);
int is_same = memcmp(&embed_data[0], f_ptr, f_size);
// if both operations refers to the same resource/file at
// execution time and translation time, "is_same" should be 0
return is_same == 0 ? 0 : 1;
}
<IP_ADDRESS> [limit parameter]
1 Constraints
The limit standard embed parameter may appear zero times or one time in the embed parameter
sequence. Its preprocessor argument clause shall be present and have the form:
( constant-expression )
and shall be an integer constant expression. The integer constant expression shall not evaluate to a
value less than 0.
2 The token defined shall not appear within the constant expression.
Semantics
3 The embed parameter with a preprocessor parameter token limit denotes a balanced preprocessing
token sequence that will be used to compute the resource width. Independently of any macro
replacement done previously (e.g. when matching the form of #embed), the constant expression is
evaluated after the balanced preprocessing token sequence is processed as in normal text, using
the rules specified for conditional inclusion (6.10.1), with the exception that any defined macro
expressions are not permitted.
4 The resource width is:
— 0, if the integer constant expression evaluates to 0; or,
— the implementation resource width if it is less than the embed element width multiplied by
the integer constant expression; or,
— the embed element width multiplied by the integer constant expression, if it is less than or
equal to the implementation resource width.
5 EXAMPLE 1 Checking the first 4 elements of a sound resource.
#include <assert.h>
int main (int, char*[]) {
static const char sound_signature[] = {
#embed <sdk/jump.wav> limit(2+2)
};
static_assert((sizeof(sound_signature) / sizeof(*sound_signature)) == 4,
"There should only be 4 elements in this array.");
// verify PCM WAV resource
assert(sound_signature[0] == ’R’);
assert(sound_signature[1] == ’I’);
assert(sound_signature[2] == ’F’);
assert(sound_signature[3] == ’F’);
assert(sizeof(sound_signature) == 4);
return 0;
}
6 EXAMPLE 2 Similar to a previous example, except it illustrates macro expansion specifically done for the limit(...)
parameter.
#include <assert.h>
#define TWO_PLUS_TWO 2+2
int main (int, char*[]) {
const char sound_signature[] = {
/* the token sequence within the parentheses
for the "limit" parameter undergoes macro
expansion, at least once, resulting in
#embed <sdk/jump.wav> limit(2+2)
*/
#embed <sdk/jump.wav> limit(TWO_PLUS_TWO)
};
static_assert((sizeof(sound_signature) / sizeof(*sound_signature)) == 4,
"There should only be 4 elements in this array.");
// verify PCM WAV resource
assert(sound_signature[0] == ’R’);
assert(sound_signature[1] == ’I’);
assert(sound_signature[2] == ’F’);
assert(sound_signature[3] == ’F’);
assert(sizeof(sound_signature) == 4);
return 0;
}
7 EXAMPLE 3 A potential constraint violation from a resource that may not have enough information in an environment that
has a CHAR_BIT greater than 24.
int main (int, char*[]) {
const unsigned char arr[] = {
#embed "24_bits.bin" limit(1) // may be a constraint violation
};
return 0;
}
<IP_ADDRESS> [suffix parameter]
1 Constraints
The suffix standard embed parameter may appear zero times or one time in the embed parameter
sequence. Its preprocessor argument clause shall be present and have the form:
( pp-balanced-token-sequenceopt )
Semantics
The embed parameter with a preprocessing parameter token suffix denotes a balanced preprocess-
ing token sequence within its preprocessor argument clause that will be placed immediately after
the result of the associated #embed directive’s expansion.
2 If the resource is empty, then suffix has no effect and is ignored.
3 EXAMPLE 1 Extra elements added to array initializer.
#include <string.h>
#ifndef SHADER_TARGET
#define SHADER_TARGET "edith-impl.glsl"
#endif
extern char* null_term_shader_data;
void fill_in_data () {
const char internal_data[] = {
#embed SHADER_TARGET \
suffix(,)
0
};
strcpy(null_term_shader_data, internal_data);
}
<IP_ADDRESS> [prefix parameter]
1 Constraints
The prefix standard embed parameter may appear zero times or one time in the embed parameter
sequence. Its preprocessor parameter clause shall be present and have the form:
( pp-balanced-token-sequenceopt )
Semantics
2 The embed parameter with a preprocessor parameter token prefix denotes a balanced preprocessing
token sequence within its preprocessor argument clause that will be placed immediately before the
result of the associated #embed directive’s expansion, if any.
3 If the resource is empty, then prefix has no effect and is ignored.
4 EXAMPLE 1 A null-terminated character array with prefixed and suffixed tokens of additional tokens when the resource is
not empty, providing null termination and a byte order mark.
#include <string.h>
#include <assert.h>
#ifndef SHADER_TARGET
#define SHADER_TARGET "ches.glsl"
#endif
extern char* merp;
void init_data () {
const char whl[] = {
#embed SHADER_TARGET \
prefix(0xEF, 0xBB, 0xBF, ) /* UTF-8 BOM */ \
suffix(,)
0
};
// always null terminated,
// contains BOM if not-empty
int is_good = (sizeof(whl) == 1 && whl[0] == ’\0’)
|| (whl[0] == ’\xEF’ && whl[1] == ’\xBB’
&& whl[2] == ’\xBF’ && whl[sizeof(whl) - 1] == ’\0’);
assert(is_good);
strcpy(merp, whl);
}
<IP_ADDRESS> [if_empty parameter]
1 Constraints
The if_empty standard embed parameter may appear zero times or one time in the embed parameter
sequence. Its preprocessor argument clause shall be present and have the form:
( pp-balanced-token-sequenceopt )
Semantics
The embed parameter with a preprocessing parameter token if_empty denotes a balanced pre-
processing token sequence within its preprocessor argument clause that will replace the #embed
directive entirely.
If the resource is not empty, then if_empty has no effect and is ignored.
2 EXAMPLE 1 This resource is considered empty due to the limit(0) embed parameter, always. This program always returns 0,
even if the resource is searched for and found successfully by the implementation.
int main () {
return
#embed </owo/uwurandom> limit(0) prefix(1) if_empty(0)
;
// becomes:
// return 0;
}
3 EXAMPLE 2 An example similar to using the suffix embed parameter, but changed slightly.
#include <string.h>
#ifndef SHADER_TARGET
#define SHADER_TARGET "edith-impl.glsl"
#endif
extern char* null_term_shader_data;
void fill_in_data () {
const char internal_data[] = {
#embed SHADER_TARGET \
suffix(, 0) \
if_empty(0)
};
strcpy(null_term_shader_data, internal_data);
}
4 EXAMPLE 3 This resource is considered empty due to the limit(0) embed parameter, always, which means any if_empty
expressions replace the directive as specified above.
int main () {
return
#include </owo/uwurandom> limit(0) if_empty(45540)
;
}
becomes:
int main () {
return 45540;
}
6.10.4 [Macro replacement]
1 Constraints
Two replacement lists are identical if and only if the preprocessing tokens in both have the same
number, ordering, spelling, and white-space separation, where all white-space separations are
considered identical.
2 An identifier currently defined as an object-like macro shall not be redefined by another #define
preprocessing directive unless the second definition is an object-like macro definition and the two
replacement lists are identical. Likewise, an identifier currently defined as a function-like macro
shall not be redefined by another #define preprocessing directive unless the second definition is a
function-like macro definition that has the same number and spelling of parameters, and the two
replacement lists are identical.
3 There shall be white space between the identifier and the replacement list in the definition of an
object-like macro.
4 If the identifier-list in the macro definition does not end with an ellipsis, the number of arguments
(including those arguments consisting of no preprocessing tokens) in an invocation of a function-like
macro shall equal the number of parameters in the macro definition. Otherwise, there shall be at
least as many arguments in the invocation as there are parameters in the macro definition (excluding
the ...). There shall exist a ) preprocessing token that terminates the invocation.
5 The identifiers __VA_ARGS__ and __VA_OPT__ shall occur only in the replacement-list of a function-
like macro that uses the ellipsis notation in the parameters.
6 A parameter identifier in a function-like macro shall be uniquely declared within its scope.
Semantics
7 The identifier immediately following the define is called the macro name. There is one name
space for macro names. Any white-space characters preceding or following the replacement list of
preprocessing tokens are not considered part of the replacement list for either form of macro.
8 If a # preprocessing token, followed by an identifier, occurs lexically at the point at which a prepro-
cessing directive could begin, the identifier is not subject to macro replacement.
9 A preprocessing directive of the form
# define identifier replacement-list new-line
defines an object-like macro that causes each subsequent instance of the macro name[219] to be replaced
by the replacement list of preprocessing tokens that constitute the remainder of the directive. The
replacement list is then rescanned for more macro names as specified below.
Footnote 219) Since, by macro-replacement time, all character constants and string literals are preprocessing tokens, not sequences
possibly containing identifier-like subsequences (see <IP_ADDRESS>, translation phases), they are never scanned for macro names or
parameters.
10 A preprocessing directive of the form
# define identifier lparen identifier-listopt ) replacement-list new-line
# define identifier lparen ... ) replacement-list new-line
# define identifier lparen identifier-list , ... ) replacement-list new-line
defines a function-like macro with parameters, whose use is similar syntactically to a function call. The
parameters are specified by the optional list of identifiers, whose scope extends from their declaration
in the identifier list until the new-line character that terminates the #define preprocessing directive.
Each subsequent instance of the function-like macro name followed by a ( as the next preprocessing
token introduces the sequence of preprocessing tokens that is replaced by the replacement list
in the definition (an invocation of the macro). The replaced sequence of preprocessing tokens is
terminated by the matching ) preprocessing token, skipping intervening matched pairs of left and
right parenthesis preprocessing tokens. Within the sequence of preprocessing tokens making up an
invocation of a function-like macro, new-line is considered a normal white-space character.
11 The sequence of preprocessing tokens bounded by the outside-most matching parentheses forms
the list of arguments for the function-like macro. The individual arguments within the list are
separated by comma preprocessing tokens, but comma preprocessing tokens between matching
inner parentheses do not separate arguments. If there are sequences of preprocessing tokens within
the list of arguments that would otherwise act as preprocessing directives,[220] the behavior is
undefined.
Footnote 220) Despite the name, a non-directive is a preprocessing directive.
12 If there is a ... in the identifier-list in the macro definition, then the trailing arguments (if any),
including any separating comma preprocessing tokens, are merged to form a single item: the variable
arguments. The number of arguments so combined is such that, following merger, the number of
arguments is one more than the number of parameters in the macro definition (excluding the ...),
except that if there are as many arguments as named parameters, the macro invocation behaves as if
a comma token has been appended to the argument list such that variable arguments are formed
that contain no pp-tokens.
<IP_ADDRESS> [Argument substitution]
1 Syntax
va-opt-replacement:
__VA_OPT__ ( pp-tokensopt )
Description
2 Argument substitution is a process during macro expansion in which identifiers corresponding to
the parameters of the macro definition and the special constructs __VA_ARGS__ and __VA_OPT__
are replaced with token sequences from the arguments of the macro invocation and possibly of the
argument of the feature __VA_OPT__ . The latter process allows to control a substitute token sequence
that is only expanded if the argument list that corresponds to a trailing ... of the parameter list is
present and has a non-empty substitution.
Constraints
3 The identifier __VA_OPT__ shall always occur as part of the preprocessing token sequence va-opt-
replacement; its closing ) is determined by skipping intervening pairs of matching left and right
parentheses in its pp-tokens. The pp-tokens of a va-opt-replacement shall not contain __VA_OPT__ .
The pp-tokens shall form a valid replacement list for the current function-like macro.
Semantics
4 After the arguments for the invocation of a function-like macro have been identified, argument
substitution takes place. A va-opt-replacement is treated as if it were a parameter. For each parameter
in the replacement list that is neither preceded by a # or ## preprocessing token nor followed by a
## preprocessing token, the preprocessing tokens naming the parameter are replaced by a token
sequence determined as follows:
— If the parameter is of the form va-opt-replacement, the replacement preprocessing tokens are
the preprocessing token sequence for the corresponding argument, as specified below.
— Otherwise, the replacement preprocessing tokens are the preprocessing tokens of the corre-
sponding argument after all macros contained therein have been expanded. The argument’s
preprocessing tokens are completely macro replaced before being substituted as if they formed
the rest of the preprocessing file with no other preprocessing tokens being available.
5 EXAMPLE 1
#define LPAREN() (
#define G(Q) 42
#define F(R, X, ...) __VA_OPT__(G R X) )
int x = F(LPAREN(), 0, <:-); // replaced by int x = 42;
6 An identifier __VA_ARGS__ that occurs in the replacement list is treated as if it were a parameter,
and the variable arguments form the preprocessing tokens used to replace it.
7 The preprocessing token sequence for the corresponding argument of a va-opt-replacement is
defined as follows. If a (hypothetical) substitution of __VA_ARGS__ as neither an operand of # nor
## consists of no preprocessing tokens, the argument consists of a single placemarker preprocessing
token (<IP_ADDRESS>, <IP_ADDRESS>). Otherwise, the argument consists of the results of the expansion of the
contained pp-tokens as the replacement list of the current function-like macro before removal of
placemarker tokens, rescanning, and further replacement.
8 NOTE The placemarker tokens are removed before stringization (<IP_ADDRESS>), and can be removed by rescanning and further
replacement (<IP_ADDRESS>).
9 EXAMPLE 2
#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)
#define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__)
#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ })
#define EMP
F(a, b, c) // replaced by f(0, a, b, c)
F() // replaced by f(0)
F(EMP) // replaced by f(0)
G(a, b, c) // replaced by f(0, a, b, c)
G(a, ) // replaced by f(0, a)
G(a) // replaced by f(0, a)
SDEF(foo); // replaced by S foo;
SDEF(bar, 1, 2); // replaced by S bar = { 1, 2 };
#define H1(X, ...) X __VA_OPT__(##) __VA_ARGS__
// error: ## on line above
// may not appear at the beginning of a replacement
// list (<IP_ADDRESS>)
#define H2(X, Y, ...) __VA_OPT__(X ## Y,) __VA_ARGS__
H2(a, b, c, d) // replaced by ab, c, d
#define H3(X, ...) #__VA_OPT__(X##X X##X)
H3(, 0) // replaced by ""
#define H4(X, ...) __VA_OPT__(a X ## X) ## b
H4(, 1) // replaced by a b
#define H5A(...) __VA_OPT__()/**/__VA_OPT__()
#define H5B(X) a ## X ## b
#define H5C(X) H5B(X)
H5C(H5A()) // replaced by ab
<IP_ADDRESS> [The # operator]
1 Constraints
Each # preprocessing token in the replacement list for a function-like macro shall be followed by a
parameter as the next preprocessing token in the replacement list.
Semantics
2 If, in the replacement list, a parameter is immediately preceded by a # preprocessing token, both
are replaced by a single character string literal preprocessing token that contains the spelling of the
preprocessing token sequence for the corresponding argument (excluding placemarker tokens). Let
the stringizing argument be the preprocessing token sequence for the corresponding argument with
placemarker tokens removed. Each occurrence of white space between the stringizing argument’s
preprocessing tokens becomes a single space character in the character string literal. White space
before the first preprocessing token and after the last preprocessing token composing the stringizing
argument is deleted. Otherwise, the original spelling of each preprocessing token in the stringizing
argument is retained in the character string literal, except for special handling for producing the
spelling of string literals and character constants: a \ character is inserted before each " and \
character of a character constant or string literal (including the delimiting " characters), except that
it is implementation-defined whether a \ character is inserted before the \ character beginning a
universal character name. If the replacement that results is not a valid character string literal, the
behavior is undefined. The character string literal corresponding to an empty stringizing argument
is "". The order of evaluation of # and ## operators is unspecified.
<IP_ADDRESS> [The ## operator]
1 Constraints
A ## preprocessing token shall not occur at the beginning or at the end of a replacement list for
either form of macro definition.
Semantics
2 If, in the replacement list of a function-like macro, a parameter is immediately preceded or followed
by a ## preprocessing token, the parameter is replaced by the corresponding argument’s preprocess-
ing token sequence; however, if an argument consists of no preprocessing tokens, the parameter is
replaced by a placemarker preprocessing token instead.[221]
Footnote 221) Placemarker preprocessing tokens do not appear in the syntax because they are temporary entities that exist only within
translation phase 4.
3 For both object-like and function-like macro invocations, before the replacement list is reexamined
for more macro names to replace, each instance of a ## preprocessing token in the replacement list
(not from an argument) is deleted and the preceding preprocessing token is concatenated with the
following preprocessing token. Placemarker preprocessing tokens are handled specially: concatena-
tion of two placemarkers results in a single placemarker preprocessing token, and concatenation
of a placemarker with a non-placemarker preprocessing token results in the non-placemarker pre-
processing token. If the result is not a valid preprocessing token, the behavior is undefined. The
resulting token is available for further macro replacement. The order of evaluation of ## operators is
unspecified.
4 EXAMPLE In the following fragment:
#define hash_hash # ## #
#define mkstr(a) # a
#define in_between(a) mkstr(a)
#define join(c, d) in_between(c hash_hash d)
char p[] = join(x, y); // equivalent to
// char p[] = "x ## y";
The expansion produces, at various stages:
join(x, y)
in_between(x hash_hash y)
in_between(x ## y)
mkstr(x ## y)
"x ## y"
In other words, expanding hash_hash produces a new token, consisting of two adjacent sharp signs, but this new token is
not the ## operator.
<IP_ADDRESS> [Rescanning and further replacement]
1 After all parameters in the replacement list have been substituted and # and ## processing has
taken place, all placemarker preprocessing tokens are removed. The resulting preprocessing token
sequence is then rescanned, along with all subsequent preprocessing tokens of the source file, for
more macro names to replace.
2 If the name of the macro being replaced is found during this scan of the replacement list (not
including the rest of the source file’s preprocessing tokens), it is not replaced. Furthermore, if any
nested replacements encounter the name of the macro being replaced, it is not replaced. These
nonreplaced macro name preprocessing tokens are no longer available for further replacement even
if they are later (re)examined in contexts in which that macro name preprocessing token would
otherwise have been replaced.
3 The resulting completely macro-replaced preprocessing token sequence is not processed as a prepro-
cessing directive even if it resembles one, but all pragma unary operator expressions within it are
then processed as specified in 6.10.10 below.
4 EXAMPLE There are cases where it is not clear whether a replacement is nested or not. For example, given the following
macro definitions:
#define f(a) a*g
#define g(a) f(a)
the invocation
f(2)(9)
could expand to either
2*f(9)
or
2*9*g
Strictly conforming programs are not permitted to depend on such unspecified behavior.
<IP_ADDRESS> [Scope of macro definitions]
1 A macro definition lasts (independent of block structure) until a corresponding #undef directive is
encountered or (if none is encountered) until the end of the preprocessing translation unit. Macro
definitions have no significance after translation phase 4.
2 A preprocessing directive of the form
# undef identifier new-line
causes the specified identifier no longer to be defined as a macro name. It is ignored if the specified
identifier is not currently defined as a macro name.
3 EXAMPLE 1 The simplest use of this facility is to define a "manifest constant", as in
#define TABSIZE 100
int table[TABSIZE];
4 EXAMPLE 2 The following defines a function-like macro whose value is the maximum of its arguments. It has the advantages
of working for any compatible types of the arguments and of generating in-line code without the overhead of function calling.
It has the disadvantages of evaluating one or the other of its arguments a second time (including side effects) and generating
more code than a function if invoked several times. It also cannot have its address taken, as it has none.
#define max(a, b) ((a) > (b) ? (a): (b))
The parentheses ensure that the arguments and the resulting expression are bound properly.
5 EXAMPLE 3 To illustrate the rules for redefinition and reexamination, the sequence
#define x 3
#define f(a) f(x * (a))
#undef x
#define x 2
#define g f
#define z z[0]
#define h g(\~{ }
#define m(a) a(w)
#define w 0,1
#define t(a) a
#define p() int
#define q(x) x
#define r(x,y) x ## y
#define str(x) # x
f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
g(x+(3,4)-w) | h 5) & m
(f)^m(m);
p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };
char c[2][6] = { str(hello), str() };
results in
f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
f(2 * (2+(3,4)-0,1)) | f(2 * (\~{ } 5)) & f(2 * (0,1))^m(0,1);
int i[] = { 1, 23, 4, 5, };
char c[2][6] = { "hello", "" };
6 EXAMPLE 4 To illustrate the rules for creating character string literals and concatenating tokens, the sequence
#define str(s) # s
#define xstr(s) str(s)
#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \
x ## s, x ## t)
#define INCFILE(n) vers ## n
#define glue(a, b) a ## b
#define xglue(a, b) glue(a, b)
#define HIGHLOW "hello"
#define LOW LOW ", world"
debug(1, 2);
fputs(str(strncmp("abc\0d", "abc", ’\4’) // this goes away
== 0) str(: @\n), s);
#include xstr(INCFILE(2).h)
glue(HIGH, LOW);
xglue(HIGH, LOW)
results in
printf("x" "1" "= %d, x" "2" "= %s", x1, x2);
fputs(
"strncmp(\"abc\\0d\", \"abc\", ’\\4’) == 0" ": @\n",
s);
#include "vers2.h" (after macro replacement, before file access)
"hello";
"hello" ", world"
or, after concatenation of the character string literals,
printf("x1= %d, x2= %s", x1, x2);
fputs(
"strncmp(\"abc\\0d\", \"abc\", ’\\4’) == 0: @\n",
s);
#include "vers2.h" (after macro replacement, before file access)
"hello";
"hello, world"
Space around the # and ## tokens in the macro definition is optional.
7 EXAMPLE 5 To illustrate the rules for placemarker preprocessing tokens, the sequence
#define t(x,y,z) x ## y ## z
int j[] = { t(+1,2,3), t(,4,5), t(6,,7), t(8,9,),
t(10,,), t(,11,), t(,,12), t(,,) };
results in
int j[] = { 123, 45, 67, 89,
10, 11, 12, };
8 EXAMPLE 6 To demonstrate the redefinition rules, the following sequence is valid.
#define OBJ_LIKE (1-1)
#define OBJ_LIKE /* white space */ (1-1) /* other */
#define FUNC_LIKE(a) (a)
#define FUNC_LIKE(a)( /* note the white space */ \
a /* other stuff on this line
*/)
But the following redefinitions are invalid:
#define OBJ_LIKE (0) // different token sequence
#define OBJ_LIKE (1 - 1) // different white space
#define FUNC_LIKE(b) (a) // different parameter usage
#define FUNC_LIKE(b) (b) // different parameter spelling
9 EXAMPLE 7 Finally, to show the variable argument list macro facilities:
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define showlist(...) puts(#__VA_ARGS__)
#define report(test, ...) ((test)?puts(#test):\
printf(__VA_ARGS__))
debug("Flag");
debug("X = %d\n", x);
showlist(The first, second, and third items.);
report(x>y, "x is %d but y is %d", x, y);
results in
fprintf(stderr, "Flag");
fprintf(stderr, "X = %d\n", x);
puts("The first, second, and third items.");
((x>y)?puts("x>y"):
printf("x is %d but y is %d", x, y));
6.10.5 [Line control]
1 Constraints
The string literal of a #line directive, if present, shall be a character string literal.
Semantics
2 The line number of the current source line is one greater than the number of new-line characters read
or introduced in translation phase 1 (<IP_ADDRESS>) while processing the source file to the current token.
3 If a preprocessing token (in particular __LINE__ ) spans two or more physical lines, it is unspecified
which of those line numbers is associated with that token. If a preprocessing directive spans two or
more physical lines, it is unspecified which of those line numbers is associated with the preprocessing
directive. If a macro invocation spans multiple physical or logical lines, it is unspecified which of
those line numbers is associated with that invocation. The line number of a preprocessing token is
independent of the context (in particular, as a macro argument or in a preprocessing directive). The
line number of a __LINE__ in a macro body is the line number of the macro invocation.
4 A preprocessing directive of the form
# line digit-sequence new-line
causes the implementation to behave as if the following sequence of source lines begins with a
source line that has a line number as specified by the digit sequence (interpreted as a decimal integer,
ignoring any optional digit separators (<IP_ADDRESS>) in the digit sequence). The digit sequence shall not
specify zero, nor a number greater than<PHONE_NUMBER>.
5 A preprocessing directive of the form
# line digit-sequence " s-char-sequenceopt " new-line
sets the presumed line number similarly and changes the presumed name of the source file to be the
contents of the character string literal.
6 A preprocessing directive of the form
# line pp-tokens new-line
(that does not match one of the two previous forms) is permitted. The preprocessing tokens after
line on the directive are processed just as in normal text (each identifier currently defined as a
macro name is replaced by its replacement list of preprocessing tokens). The directive resulting after