4 The value of a decimal constant is computed base 10; that of an octal constant, base 8;
that of a hexadecimal constant, base 16. The lexically first digit is the most significant.
5 The type of an integer constant is the first of the corresponding list in which its value can
be represented.
Octal or Hexadecimal
Suffix Decimal Constant Constant
none int int
long int unsigned int
long long int long int
unsigned long int
long long int
unsigned long long int
u or U unsigned int unsigned int
unsigned long int unsigned long int
unsigned long long int unsigned long long int
l or L long int long int
long long int unsigned long int
long long int
unsigned long long int
Both u or U unsigned long int unsigned long int
and l or L unsigned long long int unsigned long long int
ll or LL long long int long long int
unsigned long long int
Both u or U unsigned long long int unsigned long long int
and ll or LL
6 If an integer constant cannot be represented by any type in its list, it may have an
extended integer type, if the extended integer type can represent its value. If all of the
types in the list for the constant are signed, the extended integer type shall be signed. If
all of the types in the list for the constant are unsigned, the extended integer type shall be
unsigned. If the list contains both signed and unsigned types, the extended integer type
may be signed or unsigned. If an integer constant cannot be represented by any type in
its list and has no extended integer type, then the integer constant has no type.
<IP_ADDRESS> [Floating constants]
1 Syntax
floating-constant:
decimal-floating-constant
hexadecimal-floating-constant
decimal-floating-constant:
fractional-constant exponent-partopt floating-suffixopt
digit-sequence exponent-part floating-suffixopt
hexadecimal-floating-constant:
hexadecimal-prefix hexadecimal-fractional-constant
binary-exponent-part floating-suffixopt
hexadecimal-prefix hexadecimal-digit-sequence
binary-exponent-part floating-suffixopt
fractional-constant:
digit-sequenceopt . digit-sequence
digit-sequence .
exponent-part:
e signopt digit-sequence
E signopt digit-sequence
sign: one of
+ -
digit-sequence:
digit
digit-sequence digit
hexadecimal-fractional-constant:
hexadecimal-digit-sequenceopt .
hexadecimal-digit-sequence
hexadecimal-digit-sequence .
binary-exponent-part:
p signopt digit-sequence
P signopt digit-sequence
hexadecimal-digit-sequence:
hexadecimal-digit
hexadecimal-digit-sequence hexadecimal-digit
floating-suffix: one of
f l F L
Description
2 A floating constant has a significand part that may be followed by an exponent part and a
suffix that specifies its type. The components of the significand part may include a digit
sequence representing the whole-number part, followed by a period (.), followed by a
digit sequence representing the fraction part. The components of the exponent part are an
e, E, p, or P followed by an exponent consisting of an optionally signed digit sequence.
Either the whole-number part or the fraction part has to be present; for decimal floating
constants, either the period or the exponent part has to be present.
Semantics
3 The significand part is interpreted as a (decimal or hexadecimal) rational number; the
digit sequence in the exponent part is interpreted as a decimal integer. For decimal
floating constants, the exponent indicates the power of 10 by which the significand part is
to be scaled. For hexadecimal floating constants, the exponent indicates the power of 2
by which the significand part is to be scaled. For decimal floating constants, and also for
hexadecimal floating constants when FLT_RADIX is not a power of 2, the result is either
the nearest representable value, or the larger or smaller representable value immediately
adjacent to the nearest representable value, chosen in an implementation-defined manner.
For hexadecimal floating constants when FLT_RADIX is a power of 2, the result is
correctly rounded.
4 An unsuffixed floating constant has type double. If suffixed by the letter f or F, it has
type float. If suffixed by the letter l or L, it has type long double.
5 Floating constants are converted to internal format as if at translation-time. The
conversion of a floating constant shall not raise an exceptional condition or a floating-
point exception at execution time.
Recommended practice
6 The implementation should produce a diagnostic message if a hexadecimal constant
cannot be represented exactly in its evaluation format; the implementation should then
proceed with the translation of the program.
7 The translation-time conversion of floating constants should match the execution-time
conversion of character strings by library functions, such as strtod, given matching
inputs suitable for both conversions, the same result format, and default execution-time
rounding.[64]
Footnote 64) The specification for the library functions recommends more accurate conversion than required for
floating constants (see <IP_ADDRESS>).
<IP_ADDRESS> [Enumeration constants]
1 Syntax
enumeration-constant:
identifier
Semantics
2 An identifier declared as an enumeration constant has type int.
Forward references: enumeration specifiers (<IP_ADDRESS>).
<IP_ADDRESS> [Character constants]
1 Syntax
character-constant:
' c-char-sequence '
L' c-char-sequence '
c-char-sequence:
c-char
c-char-sequence c-char
c-char:
any member of the source character set except
the single-quote ', backslash \, or new-line character
escape-sequence
escape-sequence:
simple-escape-sequence
octal-escape-sequence
hexadecimal-escape-sequence
universal-character-name
simple-escape-sequence: one of
\' \" \? \\
\a \b \f \n \r \t \v
octal-escape-sequence:
\ octal-digit
\ octal-digit octal-digit
\ octal-digit octal-digit octal-digit
hexadecimal-escape-sequence:
\x hexadecimal-digit
hexadecimal-escape-sequence hexadecimal-digit
Description
2 An integer character constant is a sequence of one or more multibyte characters enclosed
in single-quotes, as in 'x'. A wide character constant is the same, except prefixed by the
letter L. With a few exceptions detailed later, the elements of the sequence are any
members of the source character set; they are mapped in an implementation-defined
manner to members of the execution character set.
3 The single-quote ', the double-quote ", the question-mark ?, the backslash \, and
arbitrary integer values are representable according to the following table of escape
sequences:
single quote ' \'
double quote " \"
question mark ? \?
backslash \ \\
octal character \octal digits
hexadecimal character \x hexadecimal digits
4 The double-quote " and question-mark ? are representable either by themselves or by the
escape sequences \" and \?, respectively, but the single-quote ' and the backslash \
shall be represented, respectively, by the escape sequences \' and \\.
5 The octal digits that follow the backslash in an octal escape sequence are taken to be part
of the construction of a single character for an integer character constant or of a single
wide character for a wide character constant. The numerical value of the octal integer so
formed specifies the value of the desired character or wide character.
6 The hexadecimal digits that follow the backslash and the letter x in a hexadecimal escape
sequence are taken to be part of the construction of a single character for an integer
character constant or of a single wide character for a wide character constant. The
numerical value of the hexadecimal integer so formed specifies the value of the desired
character or wide character.
7 Each octal or hexadecimal escape sequence is the longest sequence of characters that can
constitute the escape sequence.
8 In addition, characters not in the basic character set are representable by universal
character names and certain nongraphic characters are representable by escape sequences
consisting of the backslash \ followed by a lowercase letter: \a, \b, \f, \n, \r, \t,
and \v.[65]
Constraints
Footnote 65) The semantics of these characters were discussed in 5.2.2. If any other character follows a backslash,
the result is not a token and a diagnostic is required. See ‘‘future language directions’’ (6.11.4).
9 The value of an octal or hexadecimal escape sequence shall be in the range of
representable values for the type unsigned char for an integer character constant, or
the unsigned type corresponding to wchar_t for a wide character constant.
Semantics
10 An integer character constant has type int. The value of an integer character constant
containing a single character that maps to a single-byte execution character is the
numerical value of the representation of the mapped character interpreted as an integer.
The value of an integer character constant containing more than one character (e.g.,
'ab'), or containing a character or escape sequence that does not map to a single-byte
execution character, is implementation-defined. If an integer character constant contains
a single character or escape sequence, its value is the one that results when an object with
type char whose value is that of the single character or escape sequence is converted to
type int.
11 A wide character constant has type wchar_t, an integer type defined in the
<stddef.h> header. The value of a wide character constant containing a single
multibyte character that maps to a member of the extended execution character set is the
wide character corresponding to that multibyte character, as defined by the mbtowc
function, with an implementation-defined current locale. The value of a wide character
constant containing more than one multibyte character, or containing a multibyte
character or escape sequence not represented in the extended execution character set, is
implementation-defined.
12 EXAMPLE 1 The construction '\0' is commonly used to represent the null character.
13 EXAMPLE 2 Consider implementations that use two’s-complement representation for integers and eight
bits for objects that have type char. In an implementation in which type char has the same range of
values as signed char, the integer character constant '\xFF' has the value −1; if type char has the
same range of values as unsigned char, the character constant '\xFF' has the value +255.
14 EXAMPLE 3 Even if eight bits are used for objects that have type char, the construction '\x123'
specifies an integer character constant containing only one character, since a hexadecimal escape sequence
is terminated only by a non-hexadecimal character. To specify an integer character constant containing the
two characters whose values are '\x12' and '3', the construction '\0223' may be used, since an octal
escape sequence is terminated after three octal digits. (The value of this two-character integer character
constant is implementation-defined.)
15 EXAMPLE 4 Even if 12 or more bits are used for objects that have type wchar_t, the construction
L'\1234' specifies the implementation-defined value that results from the combination of the values
0123 and '4'.
Forward references: common definitions <stddef.h> (7.17), the mbtowc function
(<IP_ADDRESS>).
6.4.5 [String literals]
1 Syntax
string-literal:
" s-char-sequenceopt "
L" s-char-sequenceopt "
s-char-sequence:
s-char
s-char-sequence s-char
s-char:
any member of the source character set except
the double-quote ", backslash \, or new-line character
escape-sequence
Description
2 A character string literal is a sequence of zero or more multibyte characters enclosed in
double-quotes, as in "xyz". A wide string literal is the same, except prefixed by the
letter L.
3 The same considerations apply to each element of the sequence in a character string
literal or a wide string literal as if it were in an integer character constant or a wide
character constant, except that the single-quote ' is representable either by itself or by the
escape sequence \', but the double-quote " shall be represented by the escape sequence
\".
Semantics
4 In translation phase 6, the multibyte character sequences specified by any sequence of
adjacent character and wide string literal tokens are concatenated into a single multibyte
character sequence. If any of the tokens are wide string literal tokens, the resulting
multibyte character sequence is treated as a wide string literal; otherwise, it is treated as a
character string literal.
5 In translation phase 7, a byte or code of value zero is appended to each multibyte
character sequence that results from a string literal or literals.[66] The multibyte character
sequence is then used to initialize an array of static storage duration and length just
sufficient to contain the sequence. For character string literals, the array elements have
type char, and are initialized with the individual bytes of the multibyte character
sequence; for wide string literals, the array elements have type wchar_t, and are
initialized with the sequence of wide characters corresponding to the multibyte character
sequence, as defined by the mbstowcs function with an implementation-defined current
locale. The value of a string literal containing a multibyte character or escape sequence
not represented in the execution character set is implementation-defined.
Footnote 66) A character string literal need not be a string (see 7.1.1), because a null character may be embedded in
it by a \0 escape sequence.
6 It is unspecified whether these arrays are distinct provided their elements have the
appropriate values. If the program attempts to modify such an array, the behavior is
undefined.
7 EXAMPLE This pair of adjacent character string literals
"\x12" "3"
produces a single character string literal containing the two characters whose values are '\x12' and '3',
because escape sequences are converted into single members of the execution character set just prior to
adjacent string literal concatenation.
Forward references: common definitions <stddef.h> (7.17), the mbstowcs
function (<IP_ADDRESS>).
6.4.6 [Punctuators]
1 Syntax
punctuator: one of
[ ] ( ) { } . ->
++ -- & * + - ~ !
/ % << >> < > <= >= == != ^ | && ||
? : ; ...
= *= /= %= += -= <<= >>= &= ^= |=
, # ##
<: :> <% %> %: %:%:
Semantics
2 A punctuator is a symbol that has independent syntactic and semantic significance.
Depending on context, it may specify an operation to be performed (which in turn may
yield a value or a function designator, produce a side effect, or some combination thereof)
in which case it is known as an operator (other forms of operator also exist in some
contexts). An operand is an entity on which an operator acts.
3 In all aspects of the language, the six tokens[67]
<: :> <% %> %: %:%:
behave, respectively, the same as the six tokens
[ ] { } # ##
except for their spelling.[68]
Forward references: expressions (6.5), declarations (6.7), preprocessing directives
(6.10), statements (6.8).
Footnote 67) These tokens are sometimes called ‘‘digraphs’’.
Footnote 68) Thus [ and <: behave differently when ‘‘stringized’’ (see <IP_ADDRESS>), but can otherwise be freely
interchanged.
6.4.7 [Header names]
1 Syntax
header-name:
< h-char-sequence >
" q-char-sequence "
h-char-sequence:
h-char
h-char-sequence h-char
h-char:
any member of the source character set except
the new-line character and >
q-char-sequence:
q-char
q-char-sequence q-char
q-char:
any member of the source character set except
the new-line character and "
Semantics
2 The sequences in both forms of header names are mapped in an implementation-defined
manner to headers or external source file names as specified in 6.10.2.
3 If the characters ', \, ", //, or /* occur in the sequence between the < and > delimiters,
the behavior is undefined. Similarly, if the characters ', \, //, or /* occur in the
sequence between the " delimiters, the behavior is undefined.[69] Header name
preprocessing tokens are recognized only within #include preprocessing directives and
in implementation-defined locations within #pragma directives.[70]
Footnote 69) Thus, sequences of characters that resemble escape sequences cause undefined behavior.
Footnote 70) For an example of a header name preprocessing token used in a #pragma directive, see 6.10.9.
4 EXAMPLE The following sequence of characters:
0x3<1/a.h>1e2
#include <1/a.h>
#define const.member@$
forms the following sequence of preprocessing tokens (with each individual preprocessing token delimited
by a { on the left and a } on the right).
{0x3}{<}{1}{/}{a}{.}{h}{>}{1e2}
{#}{include} {<1/a.h>}
{#}{define} {const}{.}{member}{@}{$}
Forward references: source file inclusion (6.10.2).
6.4.8 [Preprocessing numbers]
1 Syntax
pp-number:
digit
. digit
pp-number digit
pp-number identifier-nondigit
pp-number e sign
pp-number E sign
pp-number p sign
pp-number P sign
pp-number .
Description
2 A preprocessing number begins with a digit optionally preceded by a period (.) and may
be followed by valid identifier characters and the character sequences e+, e-, E+, E-,
p+, p-, P+, or P-.
3 Preprocessing number tokens lexically include all floating and integer constant tokens.
Semantics
4 A preprocessing number does not have type or a value; it acquires both after a successful
conversion (as part of translation phase 7) to a floating constant token or an integer
constant token.
6.4.9 [Comments]
1 Except within a character constant, a string literal, or a comment, the characters /*
introduce a comment. The contents of such a comment are examined only to identify
multibyte characters and to find the characters */ that terminate it.[71]
Footnote 71) Thus, /* ... */ comments do not nest.
2 Except within a character constant, a string literal, or a comment, the characters //
introduce a comment that includes all multibyte characters up to, but not including, the
next new-line character. The contents of such a comment are examined only to identify
multibyte characters and to find the terminating new-line character.
3 EXAMPLE
"a//b" // four-character string literal
#include "//e" // undefined behavior
// */ // comment, not syntax error
f = g/**//h; // equivalent to f = g / h;
//\
i(); // part of a two-line comment
/\
/ j(); // part of a two-line comment
#define glue(x,y) x##y
glue(/,/) k(); // syntax error, not comment
/*//*/ l(); // equivalent to l();
m = n//**/o
+ p; // equivalent to m = n + p;
6.5 [Expressions]
1 An expression is a sequence of operators and operands that specifies computation of a
value, or that designates an object or a function, or that generates side effects, or that
performs a combination thereof.
2 Between the previous and next sequence point an object shall have its stored value
modified at most once by the evaluation of an expression.[72] Furthermore, the prior value
shall be read only to determine the value to be stored.[73]
Footnote 72) A floating-point status flag is not an object and can be set more than once within an expression.
Footnote 73) This paragraph renders undefined statement expressions such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;
3 The grouping of operators and operands is indicated by the syntax.[74] Except as specified
later (for the function-call (), &&, ||, ?:, and comma operators), the order of evaluation
of subexpressions and the order in which side effects take place are both unspecified.
Footnote 74) The syntax specifies the precedence of operators in the evaluation of an expression, which is the same
as the order of the major subclauses of this subclause, highest precedence first. Thus, for example, the
expressions allowed as the operands of the binary + operator (6.5.6) are those expressions defined in
~~6.5.1 through 6.5.6. The exceptions are cast expressions (6.5.4) as operands of unary operators
(6.5.3), and an operand contained between any of the following pairs of operators: grouping
parentheses () (6.5.1), subscripting brackets [] (<IP_ADDRESS>), function-call parentheses () (<IP_ADDRESS>), and
the conditional operator ?: (6.5.15).
Within each major subclause, the operators have the same precedence. Left- or right-associativity is
indicated in each subclause by the syntax for the expressions discussed therein.
4 Some operators (the unary operator ~, and the binary operators <<, >>, &, ^, and |,
collectively described as bitwise operators) are required to have operands that have
integer type. These operators yield values that depend on the internal representations of
integers, and have implementation-defined and undefined aspects for signed types.
5 If an exceptional condition occurs during the evaluation of an expression (that is, if the
result is not mathematically defined or not in the range of representable values for its
type), the behavior is undefined.
6 The effective type of an object for an access to its stored value is the declared type of the
object, if any.[75] If a value is stored into an object having no declared type through an
lvalue having a type that is not a character type, then the type of the lvalue becomes the
effective type of the object for that access and for subsequent accesses that do not modify
the stored value. If a value is copied into an object having no declared type using
memcpy or memmove, or is copied as an array of character type, then the effective type
of the modified object for that access and for subsequent accesses that do not modify the
value is the effective type of the object from which the value is copied, if it has one. For
all other accesses to an object having no declared type, the effective type of the object is
simply the type of the lvalue used for the access.
Footnote 75) Allocated objects have no declared type.
7 An object shall have its stored value accessed only by an lvalue expression that has one of
the following types:[76]
— a type compatible with the effective type of the object,
— a qualified version of a type compatible with the effective type of the object,
— a type that is the signed or unsigned type corresponding to the effective type of the
object,
— a type that is the signed or unsigned type corresponding to a qualified version of the
effective type of the object,
— an aggregate or union type that includes one of the aforementioned types among its
members (including, recursively, a member of a subaggregate or contained union), or
— a character type.
Footnote 76) The intent of this list is to specify those circumstances in which an object may or may not be aliased.
8 A floating expression may be contracted, that is, evaluated as though it were an atomic
operation, thereby omitting rounding errors implied by the source code and the
expression evaluation method.[77] The FP_CONTRACT pragma in <math.h> provides a
way to disallow contracted expressions. Otherwise, whether and how expressions are
contracted is implementation-defined.[78]
Forward references: the FP_CONTRACT pragma (7.12.2), copying functions (7.21.2).
Footnote 77) A contracted expression might also omit the raising of floating-point exceptions.
Footnote 78) This license is specifically intended to allow implementations to exploit fast machine instructions that
combine multiple C operators. As contractions potentially undermine predictability, and can even
decrease accuracy for containing expressions, their use needs to be well-defined and clearly
documented.
6.5.1 [Primary expressions]
1 Syntax
primary-expression:
identifier
constant
string-literal
( expression )
Semantics
2 An identifier is a primary expression, provided it has been declared as designating an
object (in which case it is an lvalue) or a function (in which case it is a function
designator).[79]
Footnote 79) Thus, an undeclared identifier is a violation of the syntax.
3 A constant is a primary expression. Its type depends on its form and value, as detailed in
6.4.4.
4 A string literal is a primary expression. It is an lvalue with type as detailed in 6.4.5.
5 A parenthesized expression is a primary expression. Its type and value are identical to
those of the unparenthesized expression. It is an lvalue, a function designator, or a void
expression if the unparenthesized expression is, respectively, an lvalue, a function
designator, or a void expression.
Forward references: declarations (6.7).
6.5.2 [Postfix operators]
1 Syntax
postfix-expression:
primary-expression
postfix-expression [ expression ]
postfix-expression ( argument-expression-listopt )
postfix-expression . identifier
postfix-expression -> identifier
postfix-expression ++
postfix-expression --
( type-name ) { initializer-list }
( type-name ) { initializer-list , }
argument-expression-list:
assignment-expression
argument-expression-list , assignment-expression
<IP_ADDRESS> [Array subscripting]
1 Constraints
One of the expressions shall have type ‘‘pointer to object type’’, the other expression shall
have integer type, and the result has type ‘‘type’’.
Semantics
2 A postfix expression followed by an expression in square brackets [] is a subscripted
designation of an element of an array object. The definition of the subscript operator []
is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that
apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the
initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th
element of E1 (counting from zero).
3 Successive subscript operators designate an element of a multidimensional array object.
If E is an n-dimensional array (n ≥ 2) with dimensions i × j × . . . × k, then E (used as
other than an lvalue) is converted to a pointer to an (n − 1)-dimensional array with
dimensions j × . . . × k. If the unary * operator is applied to this pointer explicitly, or
implicitly as a result of subscripting, the result is the pointed-to (n − 1)-dimensional array,
which itself is converted into a pointer if used as other than an lvalue. It follows from this
that arrays are stored in row-major order (last subscript varies fastest).
4 EXAMPLE Consider the array object defined by the declaration
int x[3][5];
Here x is a 3 × 5 array of ints; more precisely, x is an array of three element objects, each of which is an
array of five ints. In the expression x[i], which is equivalent to (*((x)+(i))), x is first converted to
a pointer to the initial array of five ints. Then i is adjusted according to the type of x, which conceptually
entails multiplying i by the size of the object to which the pointer points, namely an array of five int
objects. The results are added and indirection is applied to yield an array of five ints. When used in the
expression x[i][j], that array is in turn converted to a pointer to the first of the ints, so x[i][j]
yields an int.
Forward references: additive operators (6.5.6), address and indirection operators
(<IP_ADDRESS>), array declarators (<IP_ADDRESS>).
<IP_ADDRESS> [Function calls]
1 Constraints
The expression that denotes the called function[80] shall have type pointer to function
returning void or returning an object type other than an array type.
Footnote 80) Most often, this is the result of converting an identifier that is a function designator.
2 If the expression that denotes the called function has a type that includes a prototype, the
number of arguments shall agree with the number of parameters. Each argument shall
have a type such that its value may be assigned to an object with the unqualified version
of the type of its corresponding parameter.
Semantics
3 A postfix expression followed by parentheses () containing a possibly empty, comma-
separated list of expressions is a function call. The postfix expression denotes the called
function. The list of expressions specifies the arguments to the function.
4 An argument may be an expression of any object type. In preparing for the call to a
function, the arguments are evaluated, and each parameter is assigned the value of the
corresponding argument.[81]
Footnote 81) A function may change the values of its parameters, but these changes cannot affect the values of the
arguments. On the other hand, it is possible to pass a pointer to an object, and the function may
change the value of the object pointed to. A parameter declared to have array or function type is
adjusted to have a pointer type as described in 6.9.1.
5 If the expression that denotes the called function has type pointer to function returning an
object type, the function call expression has the same type as that object type, and has the
value determined as specified in <IP_ADDRESS>. Otherwise, the function call has type void. If
an attempt is made to modify the result of a function call or to access it after the next
sequence point, the behavior is undefined.
6 If the expression that denotes the called function has a type that does not include a
prototype, the integer promotions are performed on each argument, and arguments that
have type float are promoted to double. These are called the default argument
promotions. If the number of arguments does not equal the number of parameters, the
behavior is undefined. If the function is defined with a type that includes a prototype, and
either the prototype ends with an ellipsis (, ...) or the types of the arguments after
promotion are not compatible with the types of the parameters, the behavior is undefined.
If the function is defined with a type that does not include a prototype, and the types of
the arguments after promotion are not compatible with those of the parameters after
promotion, the behavior is undefined, except for the following cases:
— one promoted type is a signed integer type, the other promoted type is the
corresponding unsigned integer type, and the value is representable in both types;
— both types are pointers to qualified or unqualified versions of a character type or
void.
7 If the expression that denotes the called function has a type that does include a prototype,
the arguments are implicitly converted, as if by assignment, to the types of the
corresponding parameters, taking the type of each parameter to be the unqualified version
of its declared type. The ellipsis notation in a function prototype declarator causes
argument type conversion to stop after the last declared parameter. The default argument
promotions are performed on trailing arguments.
8 No other conversions are performed implicitly; in particular, the number and types of
arguments are not compared with those of the parameters in a function definition that
does not include a function prototype declarator.
9 If the function is defined with a type that is not compatible with the type (of the
expression) pointed to by the expression that denotes the called function, the behavior is
undefined.
10 The order of evaluation of the function designator, the actual arguments, and
subexpressions within the actual arguments is unspecified, but there is a sequence point
before the actual call.
11 Recursive function calls shall be permitted, both directly and indirectly through any chain
of other functions.
12 EXAMPLE In the function call
(*pf[f1()]) (f2(), f3() + f4())
the functions f1, f2, f3, and f4 may be called in any order. All side effects have to be completed before
the function pointed to by pf[f1()] is called.
Forward references: function declarators (including prototypes) (<IP_ADDRESS>), function
definitions (6.9.1), the return statement (<IP_ADDRESS>), simple assignment (<IP_ADDRESS>).
<IP_ADDRESS> [Structure and union members]
1 Constraints
The first operand of the . operator shall have a qualified or unqualified structure or union
type, and the second operand shall name a member of that type.
2 The first operand of the -> operator shall have type ‘‘pointer to qualified or unqualified
structure’’ or ‘‘pointer to qualified or unqualified union’’, and the second operand shall
name a member of the type pointed to.
Semantics
3 A postfix expression followed by the . operator and an identifier designates a member of
a structure or union object. The value is that of the named member,[82] and is an lvalue if
the first expression is an lvalue. If the first expression has qualified type, the result has
the so-qualified version of the type of the designated member.
Footnote 82) If the member used to access the contents of a union object is not the same as the member last used to
store a value in the object, the appropriate part of the object representation of the value is reinterpreted
as an object representation in the new type as described in 6.2.6 (a process sometimes called "type
punning"). This might be a trap representation.
4 A postfix expression followed by the -> operator and an identifier designates a member
of a structure or union object. The value is that of the named member of the object to
which the first expression points, and is an lvalue.[83] If the first expression is a pointer to
a qualified type, the result has the so-qualified version of the type of the designated
member.
Footnote 83) If &E is a valid pointer expression (where & is the ‘‘address-of ’’ operator, which generates a pointer to
its operand), the expression (&E)->MOS is the same as E.MOS.
5 One special guarantee is made in order to simplify the use of unions: if a union contains
several structures that share a common initial sequence (see below), and if the union
object currently contains one of these structures, it is permitted to inspect the common
initial part of any of them anywhere that a declaration of the complete type of the union is
visible. Two structures share a common initial sequence if corresponding members have
compatible types (and, for bit-fields, the same widths) for a sequence of one or more
initial members.
6 EXAMPLE 1 If f is a function returning a structure or union, and x is a member of that structure or
union, f().x is a valid postfix expression but is not an lvalue.
7 EXAMPLE 2 In:
struct s { int i; const int ci; };
struct s s;
const struct s cs;
volatile struct s vs;
the various members have the types:
s.i int
s.ci const int
cs.i const int
cs.ci const int
vs.i volatile int
vs.ci volatile const int
8 EXAMPLE 3 The following is a valid fragment:
union {
struct {
int alltypes;
} n;
struct {
int type;
int intnode;
} ni;
struct {
int type;
double doublenode;
} nf;
} u;
u.nf.type = 1;
u.nf.doublenode = 3.14;
/* ... */
if (u.n.alltypes == 1)
if (sin(u.nf.doublenode) == 0.0)
/* ... */
The following is not a valid fragment (because the union type is not visible within function f):
struct t1 { int m; };
struct t2 { int m; };
int f(struct t1 *p1, struct t2 *p2)
{
if (p1->m < 0)
p2->m = -p2->m;
return p1->m;
}
int g()
{
union {
struct t1 s1;
struct t2 s2;
} u;
/* ... */
return f(&u.s1, &u.s2);
}
Forward references: address and indirection operators (<IP_ADDRESS>), structure and union
specifiers (<IP_ADDRESS>).
<IP_ADDRESS> [Postfix increment and decrement operators]
1 Constraints
The operand of the postfix increment or decrement operator shall have qualified or
unqualified real or pointer type and shall be a modifiable lvalue.
Semantics
2 The result of the postfix ++ operator is the value of the operand. After the result is
obtained, the value of the operand is incremented. (That is, the value 1 of the appropriate
type is added to it.) See the discussions of additive operators and compound assignment
for information on constraints, types, and conversions and the effects of operations on
pointers. The side effect of updating the stored value of the operand shall occur between
the previous and the next sequence point.
3 The postfix -- operator is analogous to the postfix ++ operator, except that the value of
the operand is decremented (that is, the value 1 of the appropriate type is subtracted from
it).
Forward references: additive operators (6.5.6), compound assignment (<IP_ADDRESS>).
<IP_ADDRESS> [Compound literals]
1 Constraints
The type name shall specify an object type or an array of unknown size, but not a variable
length array type.
2 No initializer shall attempt to provide a value for an object not contained within the entire
unnamed object specified by the compound literal.
3 If the compound literal occurs outside the body of a function, the initializer list shall
consist of constant expressions.
Semantics
4 A postfix expression that consists of a parenthesized type name followed by a brace-
enclosed list of initializers is a compound literal. It provides an unnamed object whose
value is given by the initializer list.[84]
Footnote 84) Note that this differs from a cast expression. For example, a cast specifies a conversion to scalar types
or void only, and the result of a cast expression is not an lvalue.
5 If the type name specifies an array of unknown size, the size is determined by the
initializer list as specified in 6.7.8, and the type of the compound literal is that of the
completed array type. Otherwise (when the type name specifies an object type), the type
of the compound literal is that specified by the type name. In either case, the result is an
lvalue.
6 The value of the compound literal is that of an unnamed object initialized by the
initializer list. If the compound literal occurs outside the body of a function, the object
has static storage duration; otherwise, it has automatic storage duration associated with
the enclosing block.
7 All the semantic rules and constraints for initializer lists in 6.7.8 are applicable to
compound literals.[85]
Footnote 85) For example, subobjects without explicit initializers are initialized to zero.
8 String literals, and compound literals with const-qualified types, need not designate
distinct objects.[86]
Footnote 86) This allows implementations to share storage for string literals and constant compound literals with
the same or overlapping representations.
9 EXAMPLE 1 The file scope definition
int *p = (int []){2, 4};
initializes p to point to the first element of an array of two ints, the first having the value two and the
second, four. The expressions in this compound literal are required to be constant. The unnamed object
has static storage duration.
10 EXAMPLE 2 In contrast, in
void f(void)
{
int *p;
/*...*/
p = (int [2]){*p};
/*...*/
}
p is assigned the address of the first element of an array of two ints, the first having the value previously
pointed to by p and the second, zero. The expressions in this compound literal need not be constant. The
unnamed object has automatic storage duration.
11 EXAMPLE 3 Initializers with designations can be combined with compound literals. Structure objects
created using compound literals can be passed to functions without depending on member order:
drawline((struct point){.x=1, .y=1},
(struct point){.x=3, .y=4});
Or, if drawline instead expected pointers to struct point:
drawline(&(struct point){.x=1, .y=1},
&(struct point){.x=3, .y=4});
12 EXAMPLE 4 A read-only compound literal can be specified through constructions like:
(const float []){1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6}
13 EXAMPLE 5 The following three expressions have different meanings:
"/tmp/fileXXXXXX"
(char []){"/tmp/fileXXXXXX"}
(const char []){"/tmp/fileXXXXXX"}
The first always has static storage duration and has type array of char, but need not be modifiable; the last
two have automatic storage duration when they occur within the body of a function, and the first of these
two is modifiable.
14 EXAMPLE 6 Like string literals, const-qualified compound literals can be placed into read-only memory
and can even be shared. For example,
(const char []){"abc"} == "abc"
might yield 1 if the literals’ storage is shared.
15 EXAMPLE 7 Since compound literals are unnamed, a single compound literal cannot specify a circularly
linked object. For example, there is no way to write a self-referential compound literal that could be used
as the function argument in place of the named object endless_zeros below:
struct int_list { int car; struct int_list *cdr; };
struct int_list endless_zeros = {0, &endless_zeros};
eval(endless_zeros);
16 EXAMPLE 8 Each compound literal creates only a single object in a given scope:
struct s { int i; };
int f (void)
{
struct s *p = 0, *q;
int j = 0;
again:
q = p, p = &((struct s){ j++ });
if (j < 2) goto again;
return p == q && q->i == 1;
}
The function f() always returns the value 1.
17 Note that if an iteration statement were used instead of an explicit goto and a labeled statement, the
lifetime of the unnamed object would be the body of the loop only, and on entry next time around p would
have an indeterminate value, which would result in undefined behavior.
Forward references: type names (6.7.6), initialization (6.7.8).
6.5.3 [Unary operators]
1 Syntax
unary-expression:
postfix-expression
++ unary-expression
-- unary-expression
unary-operator cast-expression
sizeof unary-expression
sizeof ( type-name )
unary-operator: one of
& * + - ~ !
<IP_ADDRESS> [Prefix increment and decrement operators]
1 Constraints
The operand of the prefix increment or decrement operator shall have qualified or
unqualified real or pointer type and shall be a modifiable lvalue.
Semantics
2 The value of the operand of the prefix ++ operator is incremented. The result is the new
value of the operand after incrementation. The expression ++E is equivalent to (E+=1).
See the discussions of additive operators and compound assignment for information on
constraints, types, side effects, and conversions and the effects of operations on pointers.
3 The prefix -- operator is analogous to the prefix ++ operator, except that the value of the
operand is decremented.
Forward references: additive operators (6.5.6), compound assignment (<IP_ADDRESS>).
<IP_ADDRESS> [Address and indirection operators]
1 Constraints
The operand of the unary & operator shall be either a function designator, the result of a
[] or unary * operator, or an lvalue that designates an object that is not a bit-field and is
not declared with the register storage-class specifier.
2 The operand of the unary * operator shall have pointer type.
Semantics
3 The unary & operator yields the address of its operand. If the operand has type ‘‘type’’,
the result has type ‘‘pointer to type’’. If the operand is the result of a unary * operator,
neither that operator nor the & operator is evaluated and the result is as if both were
omitted, except that the constraints on the operators still apply and the result is not an
lvalue. Similarly, if the operand is the result of a [] operator, neither the & operator nor
the unary * that is implied by the [] is evaluated and the result is as if the & operator
were removed and the [] operator were changed to a + operator. Otherwise, the result is
a pointer to the object or function designated by its operand.
4 The unary * operator denotes indirection. If the operand points to a function, the result is
a function designator; if it points to an object, the result is an lvalue designating the
object. If the operand has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an
invalid value has been assigned to the pointer, the behavior of the unary * operator is
undefined.[87]
Forward references: storage-class specifiers (6.7.1), structure and union specifiers
(<IP_ADDRESS>).
Footnote 87) Thus, &*E is equivalent to E (even if E is a null pointer), and &(E1[E2]) to ((E1)+(E2)). It is
always true that if E is a function designator or an lvalue that is a valid operand of the unary &
operator, *&E is a function designator or an lvalue equal to E. If *P is an lvalue and T is the name of
an object pointer type, *(T)P is an lvalue that has a type compatible with that to which T points.
Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an
address inappropriately aligned for the type of object pointed to, and the address of an object after the
end of its lifetime.
<IP_ADDRESS> [Unary arithmetic operators]
1 Constraints
The operand of the unary + or - operator shall have arithmetic type; of the ~ operator,
integer type; of the ! operator, scalar type.
Semantics
2 The result of the unary + operator is the value of its (promoted) operand. The integer
promotions are performed on the operand, and the result has the promoted type.
3 The result of the unary - operator is the negative of its (promoted) operand. The integer
promotions are performed on the operand, and the result has the promoted type.
4 The result of the ~ operator is the bitwise complement of its (promoted) operand (that is,
each bit in the result is set if and only if the corresponding bit in the converted operand is
not set). The integer promotions are performed on the operand, and the result has the
promoted type. If the promoted type is an unsigned type, the expression ~E is equivalent
to the maximum value representable in that type minus E.
5 The result of the logical negation operator ! is 0 if the value of its operand compares
unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int.
The expression !E is equivalent to (0==E).
<IP_ADDRESS> [The sizeof operator]
1 Constraints
The sizeof operator shall not be applied to an expression that has function type or an
incomplete type, to the parenthesized name of such a type, or to an expression that
designates a bit-field member.
Semantics
2 The sizeof operator yields the size (in bytes) of its operand, which may be an
expression or the parenthesized name of a type. The size is determined from the type of
the operand. The result is an integer. If the type of the operand is a variable length array
type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an
integer constant.
3 When applied to an operand that has type char, unsigned char, or signed char,
(or a qualified version thereof) the result is 1. When applied to an operand that has array
type, the result is the total number of bytes in the array.[88] When applied to an operand
that has structure or union type, the result is the total number of bytes in such an object,
including internal and trailing padding.
Footnote 88) When applied to a parameter declared to have array or function type, the sizeof operator yields the
size of the adjusted (pointer) type (see 6.9.1).
4 The value of the result is implementation-defined, and its type (an unsigned integer type)
is size_t, defined in <stddef.h> (and other headers).
5 EXAMPLE 1 A principal use of the sizeof operator is in communication with routines such as storage
allocators and I/O systems. A storage-allocation function might accept a size (in bytes) of an object to
allocate and return a pointer to void. For example:
extern void *alloc(size_t);
double *dp = alloc(sizeof *dp);
The implementation of the alloc function should ensure that its return value is aligned suitably for
conversion to a pointer to double.
6 EXAMPLE 2 Another use of the sizeof operator is to compute the number of elements in an array:
sizeof array / sizeof array[0]
7 EXAMPLE 3 In this example, the size of a variable length array is computed and returned from a
function:
#include <stddef.h>
size_t fsize3(int n)
{
char b[n+3]; // variable length array
return sizeof b; // execution time sizeof
}
int main()
{
size_t size;
size = fsize3(10); // fsize3 returns 13
return 0;
}
Forward references: common definitions <stddef.h> (7.17), declarations (6.7),
structure and union specifiers (<IP_ADDRESS>), type names (6.7.6), array declarators (<IP_ADDRESS>).
6.5.4 [Cast operators]
1 Syntax
cast-expression:
unary-expression
( type-name ) cast-expression
Constraints
2 Unless the type name specifies a void type, the type name shall specify qualified or
unqualified scalar type and the operand shall have scalar type.
3 Conversions that involve pointers, other than where permitted by the constraints of
<IP_ADDRESS>, shall be specified by means of an explicit cast.
Semantics
4 Preceding an expression by a parenthesized type name converts the value of the
expression to the named type. This construction is called a cast.[89] A cast that specifies
no conversion has no effect on the type or value of an expression.
Footnote 89) A cast does not yield an lvalue. Thus, a cast to a qualified type has the same effect as a cast to the
unqualified version of the type.
5 If the value of the expression is represented with greater precision or range than required
by the type named by the cast (<IP_ADDRESS>), then the cast specifies a conversion even if the
type of the expression is the same as the named type.
Forward references: equality operators (6.5.9), function declarators (including
prototypes) (<IP_ADDRESS>), simple assignment (<IP_ADDRESS>), type names (6.7.6).
6.5.5 [Multiplicative operators]
1 Syntax
multiplicative-expression:
cast-expression
multiplicative-expression * cast-expression
multiplicative-expression / cast-expression
multiplicative-expression % cast-expression
Constraints
2 Each of the operands shall have arithmetic type. The operands of the % operator shall
have integer type.
Semantics
3 The usual arithmetic conversions are performed on the operands.
4 The result of the binary * operator is the product of the operands.
5 The result of the / operator is the quotient from the division of the first operand by the
second; the result of the % operator is the remainder. In both operations, if the value of
the second operand is zero, the behavior is undefined.
6 When integers are divided, the result of the / operator is the algebraic quotient with any
fractional part discarded.[90] If the quotient a/b is representable, the expression
(a/b)*b + a%b shall equal a.
Footnote 90) This is often called ‘‘truncation toward zero’’.
6.5.6 [Additive operators]
1 Syntax
additive-expression:
multiplicative-expression
additive-expression + multiplicative-expression
additive-expression - multiplicative-expression
Constraints
2 For addition, either both operands shall have arithmetic type, or one operand shall be a
pointer to an object type and the other shall have integer type. (Incrementing is
equivalent to adding 1.)
3 For subtraction, one of the following shall hold:
— both operands have arithmetic type;
— both operands are pointers to qualified or unqualified versions of compatible object
types; or
— the left operand is a pointer to an object type and the right operand has integer type.
(Decrementing is equivalent to subtracting 1.)
Semantics
4 If both operands have arithmetic type, the usual arithmetic conversions are performed on
them.
5 The result of the binary + operator is the sum of the operands.
6 The result of the binary - operator is the difference resulting from the subtraction of the
second operand from the first.
7 For the purposes of these operators, a pointer to an object that is not an element of an
array behaves the same as a pointer to the first element of an array of length one with the
type of the object as its element type.
8 When an expression that has integer type is added to or subtracted from a pointer, the
result has the type of the pointer operand. If the pointer operand points to an element of
an array object, and the array is large enough, the result points to an element offset from
the original element such that the difference of the subscripts of the resulting and original
array elements equals the integer expression. In other words, if the expression P points to
the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and
(P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of
the array object, provided they exist. Moreover, if the expression P points to the last
element of an array object, the expression (P)+1 points one past the last element of the
array object, and if the expression Q points one past the last element of an array object,
the expression (Q)-1 points to the last element of the array object. If both the pointer
operand and the result point to elements of the same array object, or one past the last
element of the array object, the evaluation shall not produce an overflow; otherwise, the
behavior is undefined. If the result points one past the last element of the array object, it
shall not be used as the operand of a unary * operator that is evaluated.
9 When two pointers are subtracted, both shall point to elements of the same array object,
or one past the last element of the array object; the result is the difference of the
subscripts of the two array elements. The size of the result is implementation-defined,
and its type (a signed integer type) is ptrdiff_t defined in the <stddef.h> header.
If the result is not representable in an object of that type, the behavior is undefined. In
other words, if the expressions P and Q point to, respectively, the i-th and j-th elements of
an array object, the expression (P)-(Q) has the value i−j provided the value fits in an
object of type ptrdiff_t. Moreover, if the expression P points either to an element of
an array object or one past the last element of an array object, and the expression Q points
value as ((Q)-(P))+1 and as -((P)-((Q)+1)), and has the value zero if the
expression P points one past the last element of the array object, even though the
expression (Q)+1 does not point to an element of the array object.[91]
Footnote 91) Another way to approach pointer arithmetic is first to convert the pointer(s) to character pointer(s): In
this scheme the integer expression added to or subtracted from the converted pointer is first multiplied
by the size of the object originally pointed to, and the resulting pointer is converted back to the
original type. For pointer subtraction, the result of the difference between the character pointers is
similarly divided by the size of the object originally pointed to.
When viewed in this way, an implementation need only provide one extra byte (which may overlap
another object in the program) just after the end of the object in order to satisfy the ‘‘one past the last
element’’ requirements.
10 EXAMPLE Pointer arithmetic is well defined with pointers to variable length array types.
{
int n = 4, m = 3;
int a[n][m];
int (*p)[m] = a; // p == &a[0]
p += 1; // p == &a[1]
(*p)[2] = 99; // a[1][2] == 99
n = p - a; // n == 1
}
11 If array a in the above example were declared to be an array of known constant size, and pointer p were
declared to be a pointer to an array of the same known constant size (pointing to a), the results would be
the same.
Forward references: array declarators (<IP_ADDRESS>), common definitions <stddef.h>
(7.17).
6.5.7 [Bitwise shift operators]
1 Syntax
shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression
Constraints
2 Each of the operands shall have integer type.
Semantics
3 The integer promotions are performed on each of the operands. The type of the result is
that of the promoted left operand. If the value of the right operand is negative or is
greater than or equal to the width of the promoted left operand, the behavior is undefined.
4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with
zeros. If E1 has an unsigned type, the value of the result is E1 × 2E2 , reduced modulo
one more than the maximum value representable in the result type. If E1 has a signed
type and nonnegative value, and E1 × 2E2 is representable in the result type, then that is
the resulting value; otherwise, the behavior is undefined.
5 The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type
or if E1 has a signed type and a nonnegative value, the value of the result is the integral
part of the quotient of E1 / 2E2 . If E1 has a signed type and a negative value, the
resulting value is implementation-defined.
6.5.8 [Relational operators]
1 Syntax
relational-expression:
shift-expression
relational-expression < shift-expression
relational-expression > shift-expression
relational-expression <= shift-expression
relational-expression >= shift-expression
Constraints
2 One of the following shall hold:
— both operands have real type;
— both operands are pointers to qualified or unqualified versions of compatible object
types; or
— both operands are pointers to qualified or unqualified versions of compatible
incomplete types.
Semantics
3 If both of the operands have arithmetic type, the usual arithmetic conversions are
performed.
4 For the purposes of these operators, a pointer to an object that is not an element of an
array behaves the same as a pointer to the first element of an array of length one with the
type of the object as its element type.
5 When two pointers are compared, the result depends on the relative locations in the
address space of the objects pointed to. If two pointers to object or incomplete types both
point to the same object, or both point one past the last element of the same array object,
they compare equal. If the objects pointed to are members of the same aggregate object,
pointers to structure members declared later compare greater than pointers to members
declared earlier in the structure, and pointers to array elements with larger subscript
values compare greater than pointers to elements of the same array with lower subscript
values. All pointers to members of the same union object compare equal. If the
expression P points to an element of an array object and the expression Q points to the
last element of the same array object, the pointer expression Q+1 compares greater than
P. In all other cases, the behavior is undefined.
6 Each of the operators < (less than), > (greater than), <= (less than or equal to), and >=
(greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false.[92]
The result has type int.
Footnote 92) The expression a<b<c is not interpreted as in ordinary mathematics. As the syntax indicates, it
means (a<b)<c; in other words, ‘‘if a is less than b, compare 1 to c; otherwise, compare 0 to c’’.
6.5.9 [Equality operators]
1 Syntax
equality-expression:
relational-expression
equality-expression == relational-expression
equality-expression != relational-expression
Constraints
2 One of the following shall hold:
— both operands have arithmetic type;
— both operands are pointers to qualified or unqualified versions of compatible types;
— one operand is a pointer to an object or incomplete type and the other is a pointer to a
qualified or unqualified version of void; or
— one operand is a pointer and the other is a null pointer constant.
Semantics
3 The == (equal to) and != (not equal to) operators are analogous to the relational
operators except for their lower precedence.[93] Each of the operators yields 1 if the
specified relation is true and 0 if it is false. The result has type int. For any pair of
operands, exactly one of the relations is true.
Footnote 93) Because of the precedences, a<b == c<d is 1 whenever a<b and c<d have the same truth-value.
4 If both of the operands have arithmetic type, the usual arithmetic conversions are
performed. Values of complex types are equal if and only if both their real parts are equal
and also their imaginary parts are equal. Any two values of arithmetic types from
different type domains are equal if and only if the results of their conversions to the
(complex) result type determined by the usual arithmetic conversions are equal.
5 Otherwise, at least one operand is a pointer. If one operand is a pointer and the other is a
null pointer constant, the null pointer constant is converted to the type of the pointer. If
one operand is a pointer to an object or incomplete type and the other is a pointer to a
qualified or unqualified version of void, the former is converted to the type of the latter.
6 Two pointers compare equal if and only if both are null pointers, both are pointers to the
same object (including a pointer to an object and a subobject at its beginning) or function,
both are pointers to one past the last element of the same array object, or one is a pointer
to one past the end of one array object and the other is a pointer to the start of a different
array object that happens to immediately follow the first array object in the address
space.[94]
Footnote 94) Two objects may be adjacent in memory because they are adjacent elements of a larger array or
adjacent members of a structure with no padding between them, or because the implementation chose
to place them so, even though they are unrelated. If prior invalid pointer operations (such as accesses
outside array bounds) produced undefined behavior, subsequent comparisons also produce undefined
behavior.
7 For the purposes of these operators, a pointer to an object that is not an element of an
array behaves the same as a pointer to the first element of an array of length one with the
type of the object as its element type.
6.5.10 [Bitwise AND operator]
1 Syntax
AND-expression:
equality-expression
AND-expression & equality-expression
Constraints
2 Each of the operands shall have integer type.
Semantics
3 The usual arithmetic conversions are performed on the operands.
4 The result of the binary & operator is the bitwise AND of the operands (that is, each bit in
the result is set if and only if each of the corresponding bits in the converted operands is
set).
6.5.11 [Bitwise exclusive OR operator]
1 Syntax
exclusive-OR-expression:
AND-expression
exclusive-OR-expression ^ AND-expression
Constraints
2 Each of the operands shall have integer type.
Semantics
3 The usual arithmetic conversions are performed on the operands.
4 The result of the ^ operator is the bitwise exclusive OR of the operands (that is, each bit
in the result is set if and only if exactly one of the corresponding bits in the converted
operands is set).
6.5.12 [Bitwise inclusive OR operator]
1 Syntax
inclusive-OR-expression:
exclusive-OR-expression
inclusive-OR-expression | exclusive-OR-expression
Constraints
2 Each of the operands shall have integer type.
Semantics
3 The usual arithmetic conversions are performed on the operands.
4 The result of the | operator is the bitwise inclusive OR of the operands (that is, each bit in
the result is set if and only if at least one of the corresponding bits in the converted
operands is set).
6.5.13 [Logical AND operator]
1 Syntax
logical-AND-expression:
inclusive-OR-expression
logical-AND-expression && inclusive-OR-expression
Constraints
2 Each of the operands shall have scalar type.
Semantics
3 The && operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it
yields 0. The result has type int.
4 Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation;
there is a sequence point after the evaluation of the first operand. If the first operand
compares equal to 0, the second operand is not evaluated.
6.5.14 [Logical OR operator]
1 Syntax
logical-OR-expression:
logical-AND-expression
logical-OR-expression || logical-AND-expression
Constraints
2 Each of the operands shall have scalar type.
Semantics
3 The || operator shall yield 1 if either of its operands compare unequal to 0; otherwise, it
yields 0. The result has type int.
4 Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; there is
a sequence point after the evaluation of the first operand. If the first operand compares
unequal to 0, the second operand is not evaluated.
6.5.15 [Conditional operator]
1 Syntax
conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression
Constraints
2 The first operand shall have scalar type.
3 One of the following shall hold for the second and third operands:
— both operands have arithmetic type;
— both operands have the same structure or union type;
— both operands have void type;
— both operands are pointers to qualified or unqualified versions of compatible types;
— one operand is a pointer and the other is a null pointer constant; or
— one operand is a pointer to an object or incomplete type and the other is a pointer to a
qualified or unqualified version of void.
Semantics
4 The first operand is evaluated; there is a sequence point after its evaluation. The second
operand is evaluated only if the first compares unequal to 0; the third operand is evaluated
only if the first compares equal to 0; the result is the value of the second or third operand
(whichever is evaluated), converted to the type described below.[95] If an attempt is made
to modify the result of a conditional operator or to access it after the next sequence point,
the behavior is undefined.
Footnote 95) A conditional expression does not yield an lvalue.
5 If both the second and third operands have arithmetic type, the result type that would be
determined by the usual arithmetic conversions, were they applied to those two operands,
is the type of the result. If both the operands have structure or union type, the result has
that type. If both operands have void type, the result has void type.
6 If both the second and third operands are pointers or one is a null pointer constant and the
other is a pointer, the result type is a pointer to a type qualified with all the type qualifiers
of the types pointed-to by both operands. Furthermore, if both operands are pointers to
compatible types or to differently qualified versions of compatible types, the result type is
a pointer to an appropriately qualified version of the composite type; if one operand is a
null pointer constant, the result has the type of the other operand; otherwise, one operand
is a pointer to void or a qualified version of void, in which case the result type is a
pointer to an appropriately qualified version of void.
7 EXAMPLE The common type that results when the second and third operands are pointers is determined
in two independent stages. The appropriate qualifiers, for example, do not depend on whether the two
pointers have compatible types.
8 Given the declarations
const void *c_vp;
void *vp;
const int *c_ip;
volatile int *v_ip;
int *ip;
const char *c_cp;
the third column in the following table is the common type that is the result of a conditional expression in
which the first two columns are the second and third operands (in either order):
c_vp c_ip const void *
v_ip 0 volatile int *
c_ip v_ip const volatile int *
vp c_cp const void *
ip c_ip const int *
vp ip void *
6.5.16 [Assignment operators]
1 Syntax
assignment-expression:
conditional-expression
unary-expression assignment-operator assignment-expression
assignment-operator: one of
= *= /= %= += -= <<= >>= &= ^= |=
Constraints
2 An assignment operator shall have a modifiable lvalue as its left operand.
Semantics
3 An assignment operator stores a value in the object designated by the left operand. An
assignment expression has the value of the left operand after the assignment, but is not an
lvalue. The type of an assignment expression is the type of the left operand unless the
left operand has qualified type, in which case it is the unqualified version of the type of
the left operand. The side effect of updating the stored value of the left operand shall
occur between the previous and the next sequence point.
4 The order of evaluation of the operands is unspecified. If an attempt is made to modify
the result of an assignment operator or to access it after the next sequence point, the
behavior is undefined.
<IP_ADDRESS> [Simple assignment]
1 Constraints
One of the following shall hold:[96]
— the left operand has qualified or unqualified arithmetic type and the right has
arithmetic type;
— the left operand has a qualified or unqualified version of a structure or union type
compatible with the type of the right;
— both operands are pointers to qualified or unqualified versions of compatible types,
and the type pointed to by the left has all the qualifiers of the type pointed to by the
right;
— one operand is a pointer to an object or incomplete type and the other is a pointer to a
qualified or unqualified version of void, and the type pointed to by the left has all
the qualifiers of the type pointed to by the right;
— the left operand is a pointer and the right is a null pointer constant; or
— the left operand has type _Bool and the right is a pointer.
Semantics
Footnote 96) The asymmetric appearance of these constraints with respect to type qualifiers is due to the conversion
(specified in <IP_ADDRESS>) that changes lvalues to ‘‘the value of the expression’’ and thus removes any type
qualifiers that were applied to the type category of the expression (for example, it removes const but
not volatile from the type int volatile * const).
2 In simple assignment (=), the value of the right operand is converted to the type of the
assignment expression and replaces the value stored in the object designated by the left
operand.
3 If the value being stored in an object is read from another object that overlaps in any way
the storage of the first object, then the overlap shall be exact and the two objects shall
have qualified or unqualified versions of a compatible type; otherwise, the behavior is
undefined.
4 EXAMPLE 1 In the program fragment
int f(void);
char c;
/* ... */
if ((c = f()) == -1)
/* ... */
the int value returned by the function may be truncated when stored in the char, and then converted back
to int width prior to the comparison. In an implementation in which ‘‘plain’’ char has the same range of
values as unsigned char (and char is narrower than int), the result of the conversion cannot be
negative, so the operands of the comparison can never compare equal. Therefore, for full portability, the
variable c should be declared as int.
5 EXAMPLE 2 In the fragment:
char c;
int i;
long l;
l = (c = i);
the value of i is converted to the type of the assignment expression c = i, that is, char type. The value
of the expression enclosed in parentheses is then converted to the type of the outer assignment expression,
that is, long int type.
6 EXAMPLE 3 Consider the fragment:
const char **cpp;
char *p;
const char c = 'A';
cpp = &p; // constraint violation
*cpp = &c; // valid
*p = 0; // valid
The first assignment is unsafe because it would allow the following valid code to attempt to change the
value of the const object c.
<IP_ADDRESS> [Compound assignment]
1 Constraints
For the operators += and -= only, either the left operand shall be a pointer to an object
type and the right shall have integer type, or the left operand shall have qualified or
unqualified arithmetic type and the right shall have arithmetic type.
2 For the other operators, each operand shall have arithmetic type consistent with those
allowed by the corresponding binary operator.
Semantics
3 A compound assignment of the form E1 op = E2 differs from the simple assignment
expression E1 = E1 op (E2) only in that the lvalue E1 is evaluated only once.
6.5.17 [Comma operator]
1 Syntax
expression:
assignment-expression
expression , assignment-expression
Semantics
2 The left operand of a comma operator is evaluated as a void expression; there is a
sequence point after its evaluation. Then the right operand is evaluated; the result has its
type and value.[97] If an attempt is made to modify the result of a comma operator or to
access it after the next sequence point, the behavior is undefined.
Footnote 97) A comma operator does not yield an lvalue.
3 EXAMPLE As indicated by the syntax, the comma operator (as described in this subclause) cannot
appear in contexts where a comma is used to separate items in a list (such as arguments to functions or lists
of initializers). On the other hand, it can be used within a parenthesized expression or within the second
expression of a conditional operator in such contexts. In the function call
f(a, (t=3, t+2), c)
the function has three arguments, the second of which has the value 5.
Forward references: initialization (6.7.8).
6.6 [Constant expressions]
1 Syntax
constant-expression:
conditional-expression
Description
2 A constant expression can be evaluated during translation rather than runtime, and
accordingly may be used in any place that a constant may be.
Constraints
3 Constant expressions shall not contain assignment, increment, decrement, function-call,
or comma operators, except when they are contained within a subexpression that is not
evaluated.[98]
Footnote 98) The operand of a sizeof operator is usually not evaluated (<IP_ADDRESS>).
4 Each constant expression shall evaluate to a constant that is in the range of representable
values for its type.
Semantics
5 An expression that evaluates to a constant is required in several contexts. If a floating
expression is evaluated in the translation environment, the arithmetic precision and range
shall be at least as great as if the expression were being evaluated in the execution
environment.
6 An integer constant expression[99] shall have integer type and shall only have operands
that are integer constants, enumeration constants, character constants, sizeof
expressions whose results are integer constants, and floating constants that are the
immediate operands of casts. Cast operators in an integer constant expression shall only
convert arithmetic types to integer types, except as part of an operand to the sizeof
operator.
Footnote 99) An integer constant expression is used to specify the size of a bit-field member of a structure, the
value of an enumeration constant, the size of an array, or the value of a case constant. Further
constraints that apply to the integer constant expressions used in conditional-inclusion preprocessing
directives are discussed in 6.10.1.
7 More latitude is permitted for constant expressions in initializers. Such a constant
expression shall be, or evaluate to, one of the following:
— an arithmetic constant expression,
— a null pointer constant,
— an address constant, or
— an address constant for an object type plus or minus an integer constant expression.
8 An arithmetic constant expression shall have arithmetic type and shall only have
operands that are integer constants, floating constants, enumeration constants, character
constants, and sizeof expressions. Cast operators in an arithmetic constant expression
shall only convert arithmetic types to arithmetic types, except as part of an operand to a
sizeof operator whose result is an integer constant.
9 An address constant is a null pointer, a pointer to an lvalue designating an object of static
storage duration, or a pointer to a function designator; it shall be created explicitly using
the unary & operator or an integer constant cast to pointer type, or implicitly by the use of
an expression of array or function type. The array-subscript [] and member-access .
and -> operators, the address & and indirection * unary operators, and pointer casts may
be used in the creation of an address constant, but the value of an object shall not be
accessed by use of these operators.
10 An implementation may accept other forms of constant expressions.
11 The semantic rules for the evaluation of a constant expression are the same as for
nonconstant expressions.[100]
Forward references: array declarators (<IP_ADDRESS>), initialization (6.7.8).
Footnote 100) Thus, in the following initialization,
static int i = 2 || 1 / 0;
the expression is a valid integer constant expression with value one.
6.7 [Declarations]
1 Syntax
declaration:
declaration-specifiers init-declarator-listopt ;
declaration-specifiers:
storage-class-specifier declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt
function-specifier declaration-specifiersopt
init-declarator-list:
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator
declarator = initializer
Constraints
2 A declaration shall declare at least a declarator (other than the parameters of a function or
the members of a structure or union), a tag, or the members of an enumeration.
3 If an identifier has no linkage, there shall be no more than one declaration of the identifier
(in a declarator or type specifier) with the same scope and in the same name space, except
for tags as specified in <IP_ADDRESS>.
4 All declarations in the same scope that refer to the same object or function shall specify
compatible types.
Semantics
5 A declaration specifies the interpretation and attributes of a set of identifiers. A definition
of an identifier is a declaration for that identifier that:
— for an object, causes storage to be reserved for that object;
— for a function, includes the function body;[101]
— for an enumeration constant or typedef name, is the (only) declaration of the
identifier.
Footnote 101) Function definitions have a different syntax, described in 6.9.1.
6 The declaration specifiers consist of a sequence of specifiers that indicate the linkage,
storage duration, and part of the type of the entities that the declarators denote. The init-
declarator-list is a comma-separated sequence of declarators, each of which may have
additional type information, or an initializer, or both. The declarators contain the
identifiers (if any) being declared.
7 If an identifier for an object is declared with no linkage, the type for the object shall be
complete by the end of its declarator, or by the end of its init-declarator if it has an
initializer; in the case of function parameters (including in prototypes), it is the adjusted
type (see <IP_ADDRESS>) that is required to be complete.
Forward references: declarators (6.7.5), enumeration specifiers (<IP_ADDRESS>), initialization
(6.7.8).
6.7.1 [Storage-class specifiers]
1 Syntax
storage-class-specifier:
typedef
extern
static
auto
register
Constraints
2 At most, one storage-class specifier may be given in the declaration specifiers in a
declaration.[102]
Semantics
Footnote 102) See ‘‘future language directions’’ (6.11.5).
3 The typedef specifier is called a ‘‘storage-class specifier’’ for syntactic convenience
only; it is discussed in 6.7.7. The meanings of the various linkages and storage durations
were discussed in 6.2.2 and 6.2.4.
4 A declaration of an identifier for an object with storage-class specifier register
suggests that access to the object be as fast as possible. The extent to which such
suggestions are effective is implementation-defined.[103]
Footnote 103) The implementation may treat any register declaration simply as an auto declaration. However,
whether or not addressable storage is actually used, the address of any part of an object declared with
storage-class specifier register cannot be computed, either explicitly (by use of the unary &
operator as discussed in <IP_ADDRESS>) or implicitly (by converting an array name to a pointer as discussed in
<IP_ADDRESS>). Thus, the only operator that can be applied to an array declared with storage-class specifier
register is sizeof.
5 The declaration of an identifier for a function that has block scope shall have no explicit
storage-class specifier other than extern.
6 If an aggregate or union object is declared with a storage-class specifier other than
typedef, the properties resulting from the storage-class specifier, except with respect to
linkage, also apply to the members of the object, and so on recursively for any aggregate
or union member objects.
Forward references: type definitions (6.7.7).
6.7.2 [Type specifiers]
1 Syntax
type-specifier:
void
char
short
int
long
float
double
signed
unsigned
_Bool
_Complex
struct-or-union-specifier ∗
enum-specifier
typedef-name
Constraints
2 At least one type specifier shall be given in the declaration specifiers in each declaration,
and in the specifier-qualifier list in each struct declaration and type name. Each list of
type specifiers shall be one of the following sets (delimited by commas, when there is
more than one set on a line); the type specifiers may occur in any order, possibly
intermixed with the other declaration specifiers.
— void
— char
— signed char
— unsigned char
— short, signed short, short int, or signed short int
— unsigned short, or unsigned short int
— int, signed, or signed int
— unsigned, or unsigned int
— long, signed long, long int, or signed long int
— unsigned long, or unsigned long int
— long long, signed long long, long long int, or
signed long long int
— unsigned long long, or unsigned long long int
— float
— double
— long double
— _Bool
— float _Complex
— double _Complex
— long double _Complex
— struct or union specifier ∗
— enum specifier
— typedef name
3 The type specifier _Complex shall not be used if the implementation does not provide
complex types.[104]
Semantics
Footnote 104) Freestanding implementations are not required to provide complex types. ∗
4 Specifiers for structures, unions, and enumerations are discussed in <IP_ADDRESS> through
<IP_ADDRESS>. Declarations of typedef names are discussed in 6.7.7. The characteristics of the
other types are discussed in 6.2.5.
5 Each of the comma-separated sets designates the same type, except that for bit-fields, it is
implementation-defined whether the specifier int designates the same type as signed
int or the same type as unsigned int.
Forward references: enumeration specifiers (<IP_ADDRESS>), structure and union specifiers
(<IP_ADDRESS>), tags (<IP_ADDRESS>), type definitions (6.7.7).
<IP_ADDRESS> [Structure and union specifiers]
1 Syntax
struct-or-union-specifier:
struct-or-union identifieropt { struct-declaration-list }
struct-or-union identifier
struct-or-union:
struct
union
struct-declaration-list:
struct-declaration
struct-declaration-list struct-declaration
struct-declaration:
specifier-qualifier-list struct-declarator-list ;
specifier-qualifier-list:
type-specifier specifier-qualifier-listopt
type-qualifier specifier-qualifier-listopt
struct-declarator-list:
struct-declarator
struct-declarator-list , struct-declarator
struct-declarator:
declarator
declaratoropt : constant-expression
Constraints
2 A structure or union shall not contain a member with incomplete or function type (hence,
a structure shall not contain an instance of itself, but may contain a pointer to an instance
of itself), except that the last member of a structure with more than one named member
may have incomplete array type; such a structure (and any union containing, possibly
recursively, a member that is such a structure) shall not be a member of a structure or an
element of an array.
3 The expression that specifies the width of a bit-field shall be an integer constant
expression with a nonnegative value that does not exceed the width of an object of the
type that would be specified were the colon and expression omitted. If the value is zero,
the declaration shall have no declarator.
4 A bit-field shall have a type that is a qualified or unqualified version of _Bool, signed
int, unsigned int, or some other implementation-defined type.
Semantics
5 As discussed in 6.2.5, a structure is a type consisting of a sequence of members, whose
storage is allocated in an ordered sequence, and a union is a type consisting of a sequence
of members whose storage overlap.
6 Structure and union specifiers have the same form. The keywords struct and union
indicate that the type being specified is, respectively, a structure type or a union type.
7 The presence of a struct-declaration-list in a struct-or-union-specifier declares a new type,
within a translation unit. The struct-declaration-list is a sequence of declarations for the
members of the structure or union. If the struct-declaration-list contains no named
members, the behavior is undefined. The type is incomplete until after the } that
terminates the list.
8 A member of a structure or union may have any object type other than a variably
modified type.[105] In addition, a member may be declared to consist of a specified
number of bits (including a sign bit, if any). Such a member is called a bit-field;[106] its
width is preceded by a colon.
Footnote 105) A structure or union can not contain a member with a variably modified type because member names
are not ordinary identifiers as defined in 6.2.3.
Footnote 106) The unary & (address-of) operator cannot be applied to a bit-field object; thus, there are no pointers to
or arrays of bit-field objects.
9 A bit-field is interpreted as a signed or unsigned integer type consisting of the specified
number of bits.[107] If the value 0 or 1 is stored into a nonzero-width bit-field of type
_Bool, the value of the bit-field shall compare equal to the value stored.
Footnote 107) As specified in 6.7.2 above, if the actual type specifier used is int or a typedef-name defined as int,
then it is implementation-defined whether the bit-field is signed or unsigned.
10 An implementation may allocate any addressable storage unit large enough to hold a bit-
field. If enough space remains, a bit-field that immediately follows another bit-field in a
structure shall be packed into adjacent bits of the same unit. If insufficient space remains,
whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is
implementation-defined. The order of allocation of bit-fields within a unit (high-order to
low-order or low-order to high-order) is implementation-defined. The alignment of the
addressable storage unit is unspecified.
11 A bit-field declaration with no declarator, but only a colon and a width, indicates an
unnamed bit-field.[108] As a special case, a bit-field structure member with a width of 0
indicates that no further bit-field is to be packed into the unit in which the previous bit-
field, if any, was placed.
Footnote 108) An unnamed bit-field structure member is useful for padding to conform to externally imposed
layouts.
12 Each non-bit-field member of a structure or union object is aligned in an implementation-
defined manner appropriate to its type.
13 Within a structure object, the non-bit-field members and the units in which bit-fields
reside have addresses that increase in the order in which they are declared. A pointer to a
structure object, suitably converted, points to its initial member (or if that member is a
bit-field, then to the unit in which it resides), and vice versa. There may be unnamed
padding within a structure object, but not at its beginning.
14 The size of a union is sufficient to contain the largest of its members. The value of at
most one of the members can be stored in a union object at any time. A pointer to a
union object, suitably converted, points to each of its members (or if a member is a bit-
field, then to the unit in which it resides), and vice versa.
15 There may be unnamed padding at the end of a structure or union.
16 As a special case, the last element of a structure with more than one named member may
have an incomplete array type; this is called a flexible array member. In most situations,
the flexible array member is ignored. In particular, the size of the structure is as if the
flexible array member were omitted except that it may have more trailing padding than
the omission would imply. However, when a . (or ->) operator has a left operand that is
(a pointer to) a structure with a flexible array member and the right operand names that
member, it behaves as if that member were replaced with the longest array (with the same
element type) that would not make the structure larger than the object being accessed; the
offset of the array shall remain that of the flexible array member, even if this would differ
from that of the replacement array. If this array would have no elements, it behaves as if
it had one element but the behavior is undefined if any attempt is made to access that
element or to generate a pointer one past it.
17 EXAMPLE After the declaration:
struct s { int n; double d[]; };
the structure struct s has a flexible array member d. A typical way to use this is:
int m = /* some value */;
struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));
and assuming that the call to malloc succeeds, the object pointed to by p behaves, for most purposes, as if
p had been declared as:
struct { int n; double d[m]; } *p;
(there are circumstances in which this equivalence is broken; in particular, the offsets of member d might
not be the same).
18 Following the above declaration:
struct s t1 = { 0 }; // valid
struct s t2 = { 1, { 4.2 }}; // invalid
t1.n = 4; // valid
t1.d[0] = 4.2; // might be undefined behavior
The initialization of t2 is invalid (and violates a constraint) because struct s is treated as if it did not
contain member d. The assignment to t1.d[0] is probably undefined behavior, but it is possible that
sizeof (struct s) >= offsetof(struct s, d) + sizeof (double)
in which case the assignment would be legitimate. Nevertheless, it cannot appear in strictly conforming
code.
19 After the further declaration:
struct ss { int n; };
the expressions:
sizeof (struct s) >= sizeof (struct ss)
sizeof (struct s) >= offsetof(struct s, d)
are always equal to 1.
20 If sizeof (double) is 8, then after the following code is executed:
struct s *s1;
struct s *s2;
s1 = malloc(sizeof (struct s) + 64);
s2 = malloc(sizeof (struct s) + 46);
and assuming that the calls to malloc succeed, the objects pointed to by s1 and s2 behave, for most
purposes, as if the identifiers had been declared as:
struct { int n; double d[8]; } *s1;
struct { int n; double d[5]; } *s2;
21 Following the further successful assignments:
s1 = malloc(sizeof (struct s) + 10);
s2 = malloc(sizeof (struct s) + 6);
they then behave as if the declarations were:
struct { int n; double d[1]; } *s1, *s2;
and:
double *dp;
dp = &(s1->d[0]); // valid
*dp = 42; // valid
dp = &(s2->d[0]); // valid
*dp = 42; // undefined behavior
22 The assignment:
*s1 = *s2;
only copies the member n; if any of the array elements are within the first sizeof (struct s) bytes
of the structure, they might be copied or simply overwritten with indeterminate values.
Forward references: tags (<IP_ADDRESS>).
<IP_ADDRESS> [Enumeration specifiers]
1 Syntax
enum-specifier:
enum identifieropt { enumerator-list }
enum identifieropt { enumerator-list , }
enum identifier
enumerator-list:
enumerator
enumerator-list , enumerator
enumerator:
enumeration-constant
enumeration-constant = constant-expression
Constraints
2 The expression that defines the value of an enumeration constant shall be an integer
constant expression that has a value representable as an int.
Semantics
3 The identifiers in an enumerator list are declared as constants that have type int and
may appear wherever such are permitted.[109] An enumerator with = defines its
enumeration constant as the value of the constant expression. If the first enumerator has
no =, the value of its enumeration constant is 0. Each subsequent enumerator with no =
defines its enumeration constant as the value of the constant expression obtained by
adding 1 to the value of the previous enumeration constant. (The use of enumerators with
= may produce enumeration constants with values that duplicate other values in the same
enumeration.) The enumerators of an enumeration are also known as its members.
Footnote 109) Thus, the identifiers of enumeration constants declared in the same scope shall all be distinct from
each other and from other identifiers declared in ordinary declarators.
4 Each enumerated type shall be compatible with char, a signed integer type, or an
unsigned integer type. The choice of type is implementation-defined,[110] but shall be
capable of representing the values of all the members of the enumeration. The
enumerated type is incomplete until after the } that terminates the list of enumerator
declarations.
Footnote 110) An implementation may delay the choice of which integer type until all enumeration constants have
been seen.
5 EXAMPLE The following fragment:
enum hue { chartreuse, burgundy, claret=20, winedark };
enum hue col, *cp;
col = claret;
cp = &col;
if (*cp != burgundy)
/* ... */
makes hue the tag of an enumeration, and then declares col as an object that has that type and cp as a
pointer to an object that has that type. The enumerated values are in the set { 0, 1, 20, 21 }.
Forward references: tags (<IP_ADDRESS>).
<IP_ADDRESS> [Tags]
1 Constraints
A specific type shall have its content defined at most once.
2 Where two declarations that use the same tag declare the same type, they shall both use
the same choice of struct, union, or enum.
3 A type specifier of the form
enum identifier
without an enumerator list shall only appear after the type it specifies is complete.
Semantics
4 All declarations of structure, union, or enumerated types that have the same scope and
use the same tag declare the same type. The type is incomplete[111] until the closing brace
of the list defining the content, and complete thereafter.
Footnote 111) An incomplete type may only by used when the size of an object of that type is not needed. It is not
needed, for example, when a typedef name is declared to be a specifier for a structure or union, or
when a pointer to or a function returning a structure or union is being declared. (See incomplete types
in 6.2.5.) The specification has to be complete before such a function is called or defined.
5 Two declarations of structure, union, or enumerated types which are in different scopes or
use different tags declare distinct types. Each declaration of a structure, union, or
enumerated type which does not include a tag declares a distinct type.
6 A type specifier of the form
struct-or-union identifieropt { struct-declaration-list }
or
enum identifier { enumerator-list }
or
enum identifier { enumerator-list , }
declares a structure, union, or enumerated type. The list defines the structure content,
union content, or enumeration content. If an identifier is provided,[112] the type specifier
also declares the identifier to be the tag of that type.
Footnote 112) If there is no identifier, the type can, within the translation unit, only be referred to by the declaration
of which it is a part. Of course, when the declaration is of a typedef name, subsequent declarations
can make use of that typedef name to declare objects having the specified structure, union, or
enumerated type.
7 A declaration of the form
struct-or-union identifier ;
specifies a structure or union type and declares the identifier as a tag of that type.[113]
Footnote 113) A similar construction with enum does not exist.
8 If a type specifier of the form
struct-or-union identifier
occurs other than as part of one of the above forms, and no other declaration of the
identifier as a tag is visible, then it declares an incomplete structure or union type, and
declares the identifier as the tag of that type.[113]
Footnote 113) A similar construction with enum does not exist.
9 If a type specifier of the form
struct-or-union identifier
or
enum identifier
occurs other than as part of one of the above forms, and a declaration of the identifier as a
tag is visible, then it specifies the same type as that other declaration, and does not
redeclare the tag.
10 EXAMPLE 1 This mechanism allows declaration of a self-referential structure.
struct tnode {
int count;
struct tnode *left, *right;
};
specifies a structure that contains an integer and two pointers to objects of the same type. Once this
declaration has been given, the declaration
struct tnode s, *sp;
declares s to be an object of the given type and sp to be a pointer to an object of the given type. With
these declarations, the expression sp->left refers to the left struct tnode pointer of the object to
which sp points; the expression s.right->count designates the count member of the right struct
tnode pointed to from s.
11 The following alternative formulation uses the typedef mechanism:
typedef struct tnode TNODE;
struct tnode {
int count;
TNODE *left, *right;
};
TNODE s, *sp;
12 EXAMPLE 2 To illustrate the use of prior declaration of a tag to specify a pair of mutually referential
structures, the declarations
struct s1 { struct s2 *s2p; /* ... */ }; // D1
struct s2 { struct s1 *s1p; /* ... */ }; // D2
specify a pair of structures that contain pointers to each other. Note, however, that if s2 were already
declared as a tag in an enclosing scope, the declaration D1 would refer to it, not to the tag s2 declared in
D2. To eliminate this context sensitivity, the declaration
struct s2;
may be inserted ahead of D1. This declares a new tag s2 in the inner scope; the declaration D2 then
completes the specification of the new type.
Forward references: declarators (6.7.5), array declarators (<IP_ADDRESS>), type definitions
(6.7.7).
6.7.3 [Type qualifiers]
1 Syntax
type-qualifier:
const
restrict
volatile
Constraints
2 Types other than pointer types derived from object or incomplete types shall not be
restrict-qualified.
Semantics
3 The properties associated with qualified types are meaningful only for expressions that
are lvalues.[114]
Footnote 114) The implementation may place a const object that is not volatile in a read-only region of
storage. Moreover, the implementation need not allocate storage for such an object if its address is
never used.
4 If the same qualifier appears more than once in the same specifier-qualifier-list, either
directly or via one or more typedefs, the behavior is the same as if it appeared only
once.
5 If an attempt is made to modify an object defined with a const-qualified type through use
of an lvalue with non-const-qualified type, the behavior is undefined. If an attempt is
made to refer to an object defined with a volatile-qualified type through use of an lvalue
with non-volatile-qualified type, the behavior is undefined.[115]
Footnote 115) This applies to those objects that behave as if they were defined with qualified types, even if they are
never actually defined as objects in the program (such as an object at a memory-mapped input/output
address).
6 An object that has volatile-qualified type may be modified in ways unknown to the
implementation or have other unknown side effects. Therefore any expression referring
to such an object shall be evaluated strictly according to the rules of the abstract machine,
as described in <IP_ADDRESS>. Furthermore, at every sequence point the value last stored in the
object shall agree with that prescribed by the abstract machine, except as modified by the
unknown factors mentioned previously.[116] What constitutes an access to an object that
has volatile-qualified type is implementation-defined.
Footnote 116) A volatile declaration may be used to describe an object corresponding to a memory-mapped
input/output port or an object accessed by an asynchronously interrupting function. Actions on
objects so declared shall not be ‘‘optimized out’’ by an implementation or reordered except as
permitted by the rules for evaluating expressions.
7 An object that is accessed through a restrict-qualified pointer has a special association
with that pointer. This association, defined in <IP_ADDRESS> below, requires that all accesses to
that object use, directly or indirectly, the value of that particular pointer.[117] The intended
use of the restrict qualifier (like the register storage class) is to promote
optimization, and deleting all instances of the qualifier from all preprocessing translation
units composing a conforming program does not change its meaning (i.e., observable
behavior).
Footnote 117) For example, a statement that assigns a value returned by malloc to a single pointer establishes this
association between the allocated object and the pointer.
8 If the specification of an array type includes any type qualifiers, the element type is so-
qualified, not the array type. If the specification of a function type includes any type
qualifiers, the behavior is undefined.[118]
Footnote 118) Both of these can occur through the use of typedefs.
9 For two qualified types to be compatible, both shall have the identically qualified version
of a compatible type; the order of type qualifiers within a list of specifiers or qualifiers
does not affect the specified type.
10 EXAMPLE 1 An object declared
extern const volatile int real_time_clock;
may be modifiable by hardware, but cannot be assigned to, incremented, or decremented.
11 EXAMPLE 2 The following declarations and expressions illustrate the behavior when type qualifiers
modify an aggregate type:
const struct s { int mem; } cs = { 1 };
struct s ncs; // the object ncs is modifiable
typedef int A[2][3];
const A a = {{4, 5, 6}, {7, 8, 9}}; // array of array of const int
int *pi;
const int *pci;
ncs = cs; // valid
cs = ncs; // violates modifiable lvalue constraint for =
pi = &ncs.mem; // valid
pi = &cs.mem; // violates type constraints for =
pci = &cs.mem; // valid
pi = a[0]; // invalid: a[0] has type ‘‘const int *’’
<IP_ADDRESS> [Formal definition of restrict]
1 Let D be a declaration of an ordinary identifier that provides a means of designating an
object P as a restrict-qualified pointer to type T.
2 If D appears inside a block and does not have storage class extern, let B denote the
block. If D appears in the list of parameter declarations of a function definition, let B
denote the associated block. Otherwise, let B denote the block of main (or the block of
whatever function is called at program startup in a freestanding environment).
3 In what follows, a pointer expression E is said to be based on object P if (at some
sequence point in the execution of B prior to the evaluation of E) modifying P to point to
a copy of the array object into which it formerly pointed would change the value of E.[119]
Note that ‘‘based’’ is defined only for expressions with pointer types.
Footnote 119) In other words, E depends on the value of P itself rather than on the value of an object referenced
indirectly through P. For example, if identifier p has type (int **restrict), then the pointer
expressions p and p+1 are based on the restricted pointer object designated by p, but the pointer
expressions *p and p[1] are not.
4 During each execution of B, let L be any lvalue that has &L based on P. If L is used to
access the value of the object X that it designates, and X is also modified (by any means),
then the following requirements apply: T shall not be const-qualified. Every other lvalue
used to access the value of X shall also have its address based on P. Every access that
modifies X shall be considered also to modify P, for the purposes of this subclause. If P
is assigned the value of a pointer expression E that is based on another restricted pointer
object P2, associated with block B2, then either the execution of B2 shall begin before
the execution of B, or the execution of B2 shall end prior to the assignment. If these
requirements are not met, then the behavior is undefined.
5 Here an execution of B means that portion of the execution of the program that would
correspond to the lifetime of an object with scalar type and automatic storage duration
associated with B.
6 A translator is free to ignore any or all aliasing implications of uses of restrict.
7 EXAMPLE 1 The file scope declarations
int * restrict a;
int * restrict b;
extern int c[];
assert that if an object is accessed using one of a, b, or c, and that object is modified anywhere in the
program, then it is never accessed using either of the other two.
8 EXAMPLE 2 The function parameter declarations in the following example
void f(int n, int * restrict p, int * restrict q)
{
while (n-- > 0)
*p++ = *q++;
}
assert that, during each execution of the function, if an object is accessed through one of the pointer
parameters, then it is not also accessed through the other.
9 The benefit of the restrict qualifiers is that they enable a translator to make an effective dependence
analysis of function f without examining any of the calls of f in the program. The cost is that the
programmer has to examine all of those calls to ensure that none give undefined behavior. For example, the
second call of f in g has undefined behavior because each of d[1] through d[49] is accessed through
both p and q.
void g(void)
{
extern int d[100];
f(50, d + 50, d); // valid
f(50, d + 1, d); // undefined behavior
}
10 EXAMPLE 3 The function parameter declarations
void h(int n, int * restrict p, int * restrict q, int * restrict r)
{
int i;
for (i = 0; i < n; i++)
p[i] = q[i] + r[i];
}
illustrate how an unmodified object can be aliased through two restricted pointers. In particular, if a and b
are disjoint arrays, a call of the form h(100, a, b, b) has defined behavior, because array b is not
modified within function h.
11 EXAMPLE 4 The rule limiting assignments between restricted pointers does not distinguish between a
function call and an equivalent nested block. With one exception, only ‘‘outer-to-inner’’ assignments
between restricted pointers declared in nested blocks have defined behavior.
{
int * restrict p1;
int * restrict q1;
p1 = q1; // undefined behavior
{
int * restrict p2 = p1; // valid
int * restrict q2 = q1; // valid
p1 = q2; // undefined behavior
p2 = q2; // undefined behavior
}
}
12 The one exception allows the value of a restricted pointer to be carried out of the block in which it (or, more
precisely, the ordinary identifier used to designate it) is declared when that block finishes execution. For
example, this permits new_vector to return a vector.
typedef struct { int n; float * restrict v; } vector;
vector new_vector(int n)
{
vector t;
t.n = n;
t.v = malloc(n * sizeof (float));
return t;
}
6.7.4 [Function specifiers]
1 Syntax
function-specifier:
inline
Constraints
2 Function specifiers shall be used only in the declaration of an identifier for a function.
3 An inline definition of a function with external linkage shall not contain a definition of a
modifiable object with static storage duration, and shall not contain a reference to an
identifier with internal linkage.
4 In a hosted environment, the inline function specifier shall not appear in a declaration
of main.
Semantics
5 A function declared with an inline function specifier is an inline function. The
function specifier may appear more than once; the behavior is the same as if it appeared
only once. Making a function an inline function suggests that calls to the function be as
fast as possible.[120] The extent to which such suggestions are effective is
implementation-defined.[121]
Footnote 120) By using, for example, an alternative to the usual function call mechanism, such as ‘‘inline
substitution’’. Inline substitution is not textual substitution, nor does it create a new function.
Therefore, for example, the expansion of a macro used within the body of the function uses the
definition it had at the point the function body appears, and not where the function is called; and
identifiers refer to the declarations in scope where the body occurs. Likewise, the function has a
single address, regardless of the number of inline definitions that occur in addition to the external
definition.
Footnote 121) For example, an implementation might never perform inline substitution, or might only perform inline
substitutions to calls in the scope of an inline declaration.
6 Any function with internal linkage can be an inline function. For a function with external
linkage, the following restrictions apply: If a function is declared with an inline
function specifier, then it shall also be defined in the same translation unit. If all of the
file scope declarations for a function in a translation unit include the inline function
specifier without extern, then the definition in that translation unit is an inline
definition. An inline definition does not provide an external definition for the function,
and does not forbid an external definition in another translation unit. An inline definition
provides an alternative to an external definition, which a translator may use to implement
any call to the function in the same translation unit. It is unspecified whether a call to the
function uses the inline definition or the external definition.[122]
Footnote 122) Since an inline definition is distinct from the corresponding external definition and from any other
corresponding inline definitions in other translation units, all corresponding objects with static storage
duration are also distinct in each of the definitions.
7 EXAMPLE The declaration of an inline function with external linkage can result in either an external
definition, or a definition available for use only within the translation unit. A file scope declaration with
extern creates an external definition. The following example shows an entire translation unit.
inline double fahr(double t)
{
return (9.0 * t) / 5.0 + 32.0;
}
inline double cels(double t)
{
return (5.0 * (t - 32.0)) / 9.0;
}
extern double fahr(double); // creates an external definition
double convert(int is_fahr, double temp)
{
/* A translator may perform inline substitutions */
return is_fahr ? cels(temp) : fahr(temp);
}
8 Note that the definition of fahr is an external definition because fahr is also declared with extern, but
the definition of cels is an inline definition. Because cels has external linkage and is referenced, an
external definition has to appear in another translation unit (see 6.9); the inline definition and the external
definition are distinct and either may be used for the call.
Forward references: function definitions (6.9.1).
6.7.5 [Declarators]
1 Syntax
declarator:
pointeropt direct-declarator
direct-declarator:
identifier
( declarator )
direct-declarator [ type-qualifier-listopt assignment-expressionopt ]
direct-declarator [ static type-qualifier-listopt assignment-expression ]
direct-declarator [ type-qualifier-list static assignment-expression ]
direct-declarator [ type-qualifier-listopt * ]
direct-declarator ( parameter-type-list )
direct-declarator ( identifier-listopt )
pointer:
* type-qualifier-listopt
* type-qualifier-listopt pointer
type-qualifier-list:
type-qualifier
type-qualifier-list type-qualifier
parameter-type-list:
parameter-list
parameter-list , ...
parameter-list:
parameter-declaration
parameter-list , parameter-declaration
parameter-declaration:
declaration-specifiers declarator
declaration-specifiers abstract-declaratoropt
identifier-list:
identifier
identifier-list , identifier
Semantics
2 Each declarator declares one identifier, and asserts that when an operand of the same
form as the declarator appears in an expression, it designates a function or object with the
scope, storage duration, and type indicated by the declaration specifiers.
3 A full declarator is a declarator that is not part of another declarator. The end of a full
declarator, there is a declarator specifying a variable length array type, the type specified
by the full declarator is said to be variably modified. Furthermore, any type derived by
declarator type derivation from a variably modified type is itself variably modified.
4 In the following subclauses, consider a declaration
T D1
where T contains the declaration specifiers that specify a type T (such as int) and D1 is
a declarator that contains an identifier ident. The type specified for the identifier ident in
the various forms of declarator is described inductively using this notation.
5 If, in the declaration ‘‘T D1’’, D1 has the form
identifier
then the type specified for ident is T .
6 If, in the declaration ‘‘T D1’’, D1 has the form
( D )
then ident has the type specified by the declaration ‘‘T D’’. Thus, a declarator in
parentheses is identical to the unparenthesized declarator, but the binding of complicated
declarators may be altered by parentheses.
Implementation limits
7 As discussed in <IP_ADDRESS>, an implementation may limit the number of pointer, array, and
function declarators that modify an arithmetic, structure, union, or incomplete type, either
directly or via one or more typedefs.
Forward references: array declarators (<IP_ADDRESS>), type definitions (6.7.7).
<IP_ADDRESS> [Pointer declarators]
1 Semantics
If, in the declaration ‘‘T D1’’, D1 has the form
* type-qualifier-listopt D
and the type specified for ident in the declaration ‘‘T D’’ is ‘‘derived-declarator-type-list
T ’’, then the type specified for ident is ‘‘derived-declarator-type-list type-qualifier-list
pointer to T ’’. For each type qualifier in the list, ident is a so-qualified pointer.
2 For two pointer types to be compatible, both shall be identically qualified and both shall
be pointers to compatible types.
3 EXAMPLE The following pair of declarations demonstrates the difference between a ‘‘variable pointer
to a constant value’’ and a ‘‘constant pointer to a variable value’’.
const int *ptr_to_constant;
int *const constant_ptr;
The contents of any object pointed to by ptr_to_constant shall not be modified through that pointer,
but ptr_to_constant itself may be changed to point to another object. Similarly, the contents of the
int pointed to by constant_ptr may be modified, but constant_ptr itself shall always point to the
same location.
4 The declaration of the constant pointer constant_ptr may be clarified by including a definition for the
type ‘‘pointer to int’’.
typedef int *int_ptr;
const int_ptr constant_ptr;
declares constant_ptr as an object that has type ‘‘const-qualified pointer to int’’.
<IP_ADDRESS> [Array declarators]
1 Constraints
In addition to optional type qualifiers and the keyword static, the [ and ] may delimit
an expression or *. If they delimit an expression (which specifies the size of an array), the
expression shall have an integer type. If the expression is a constant expression, it shall
have a value greater than zero. The element type shall not be an incomplete or function
type. The optional type qualifiers and the keyword static shall appear only in a
declaration of a function parameter with an array type, and then only in the outermost
array type derivation.
2 An ordinary identifier (as defined in 6.2.3) that has a variably modified type shall have
either block scope and no linkage or function prototype scope. If an identifier is declared
to be an object with static storage duration, it shall not have a variable length array type.
Semantics
3 If, in the declaration ‘‘T D1’’, D1 has one of the forms:
D[ type-qualifier-listopt assignment-expressionopt ]
D[ static type-qualifier-listopt assignment-expression ]
D[ type-qualifier-list static assignment-expression ]
D[ type-qualifier-listopt * ]
and the type specified for ident in the declaration ‘‘T D’’ is ‘‘derived-declarator-type-list
T ’’, then the type specified for ident is ‘‘derived-declarator-type-list array of T ’’.[123]
(See <IP_ADDRESS> for the meaning of the optional type qualifiers and the keyword static.)
Footnote 123) When several ‘‘array of’’ specifications are adjacent, a multidimensional array is declared.
4 If the size is not present, the array type is an incomplete type. If the size is * instead of
being an expression, the array type is a variable length array type of unspecified size,
which can only be used in declarations with function prototype scope;[124] such arrays are
nonetheless complete types. If the size is an integer constant expression and the element
type has a known constant size, the array type is not a variable length array type;
otherwise, the array type is a variable length array type.
Footnote 124) Thus, * can be used only in function declarations that are not definitions (see <IP_ADDRESS>).
5 If the size is an expression that is not an integer constant expression: if it occurs in a
declaration at function prototype scope, it is treated as if it were replaced by *; otherwise,
each time it is evaluated it shall have a value greater than zero. The size of each instance
of a variable length array type does not change during its lifetime. Where a size
expression is part of the operand of a sizeof operator and changing the value of the
size expression would not affect the result of the operator, it is unspecified whether or not
the size expression is evaluated.
6 For two array types to be compatible, both shall have compatible element types, and if
both size specifiers are present, and are integer constant expressions, then both size
specifiers shall have the same constant value. If the two array types are used in a context
which requires them to be compatible, it is undefined behavior if the two size specifiers
evaluate to unequal values.
7 EXAMPLE 1
float fa[11], *afp[17];
declares an array of float numbers and an array of pointers to float numbers.
8 EXAMPLE 2 Note the distinction between the declarations
extern int *x;
extern int y[];
The first declares x to be a pointer to int; the second declares y to be an array of int of unspecified size
(an incomplete type), the storage for which is defined elsewhere.
9 EXAMPLE 3 The following declarations demonstrate the compatibility rules for variably modified types.
extern int n;
extern int m;
void fcompat(void)
{
int a[n][6][m];
int (*p)[4][n+1];
int c[n][n][6][m];
int (*r)[n][n][n+1];
p = a; // invalid: not compatible because 4 != 6
r = c; // compatible, but defined behavior only if
// n == 6 and m == n+1
}
10 EXAMPLE 4 All declarations of variably modified (VM) types have to be at either block scope or
function prototype scope. Array objects declared with the static or extern storage-class specifier
cannot have a variable length array (VLA) type. However, an object declared with the static storage-
class specifier can have a VM type (that is, a pointer to a VLA type). Finally, all identifiers declared with a
VM type have to be ordinary identifiers and cannot, therefore, be members of structures or unions.
extern int n;
int A[n]; // invalid: file scope VLA
extern int (*p2)[n]; // invalid: file scope VM
int B[100]; // valid: file scope but not VM
void fvla(int m, int C[m][m]); // valid: VLA with prototype scope
void fvla(int m, int C[m][m]) // valid: adjusted to auto pointer to VLA
{
typedef int VLA[m][m]; // valid: block scope typedef VLA
struct tag {
int (*y)[n]; // invalid: y not ordinary identifier
int z[n]; // invalid: z not ordinary identifier
};
int D[m]; // valid: auto VLA
static int E[m]; // invalid: static block scope VLA
extern int F[m]; // invalid: F has linkage and is VLA
int (*s)[m]; // valid: auto pointer to VLA
extern int (*r)[m]; // invalid: r has linkage and points to VLA
static int (*q)[m] = &B; // valid: q is a static block pointer to VLA
}
Forward references: function declarators (<IP_ADDRESS>), function definitions (6.9.1),
initialization (6.7.8).
<IP_ADDRESS> [Function declarators (including prototypes)]
1 Constraints
A function declarator shall not specify a return type that is a function type or an array
type.
2 The only storage-class specifier that shall occur in a parameter declaration is register.
3 An identifier list in a function declarator that is not part of a definition of that function
shall be empty.
4 After adjustment, the parameters in a parameter type list in a function declarator that is
part of a definition of that function shall not have incomplete type.
Semantics
5 If, in the declaration ‘‘T D1’’, D1 has the form
D( parameter-type-list )
or
D( identifier-listopt )
and the type specified for ident in the declaration ‘‘T D’’ is ‘‘derived-declarator-type-list
T ’’, then the type specified for ident is ‘‘derived-declarator-type-list function returning
T ’’.
6 A parameter type list specifies the types of, and may declare identifiers for, the
parameters of the function.
7 A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to
type’’, where the type qualifiers (if any) are those specified within the [ and ] of the
array type derivation. If the keyword static also appears within the [ and ] of the
array type derivation, then for each call to the function, the value of the corresponding
actual argument shall provide access to the first element of an array with at least as many
elements as specified by the size expression.
8 A declaration of a parameter as ‘‘function returning type’’ shall be adjusted to ‘‘pointer to
function returning type’’, as in <IP_ADDRESS>.
9 If the list terminates with an ellipsis (, ...), no information about the number or types
of the parameters after the comma is supplied.[125]
Footnote 125) The macros defined in the <stdarg.h> header (7.15) may be used to access arguments that
correspond to the ellipsis.
10 The special case of an unnamed parameter of type void as the only item in the list
specifies that the function has no parameters.
11 If, in a parameter declaration, an identifier can be treated either as a typedef name or as a
parameter name, it shall be taken as a typedef name.
12 If the function declarator is not part of a definition of that function, parameters may have
incomplete type and may use the [*] notation in their sequences of declarator specifiers
to specify variable length array types.
13 The storage-class specifier in the declaration specifiers for a parameter declaration, if
present, is ignored unless the declared parameter is one of the members of the parameter
type list for a function definition.
14 An identifier list declares only the identifiers of the parameters of the function. An empty
list in a function declarator that is part of a definition of that function specifies that the
function has no parameters. The empty list in a function declarator that is not part of a
definition of that function specifies that no information about the number or types of the
parameters is supplied.[126]
Footnote 126) See ‘‘future language directions’’ (6.11.6).
15 For two function types to be compatible, both shall specify compatible return types.[127]
Moreover, the parameter type lists, if both are present, shall agree in the number of
parameters and in use of the ellipsis terminator; corresponding parameters shall have
compatible types. If one type has a parameter type list and the other type is specified by a
function declarator that is not part of a function definition and that contains an empty
identifier list, the parameter list shall not have an ellipsis terminator and the type of each
parameter shall be compatible with the type that results from the application of the
default argument promotions. If one type has a parameter type list and the other type is
specified by a function definition that contains a (possibly empty) identifier list, both shall
agree in the number of parameters, and the type of each prototype parameter shall be
compatible with the type that results from the application of the default argument
promotions to the type of the corresponding identifier. (In the determination of type
compatibility and of a composite type, each parameter declared with function or array
type is taken as having the adjusted type and each parameter declared with qualified type
is taken as having the unqualified version of its declared type.)
Footnote 127) If both function types are ‘‘old style’’, parameter types are not compared.
16 EXAMPLE 1 The declaration
int f(void), *fip(), (*pfi)();
declares a function f with no parameters returning an int, a function fip with no parameter specification
returning a pointer to an int, and a pointer pfi to a function with no parameter specification returning an
int. It is especially useful to compare the last two. The binding of *fip() is *(fip()), so that the
declaration suggests, and the same construction in an expression requires, the calling of a function fip,
and then using indirection through the pointer result to yield an int. In the declarator (*pfi)(), the
extra parentheses are necessary to indicate that indirection through a pointer to a function yields a function
designator, which is then used to call the function; it returns an int.
17 If the declaration occurs outside of any function, the identifiers have file scope and external linkage. If the
declaration occurs inside a function, the identifiers of the functions f and fip have block scope and either
internal or external linkage (depending on what file scope declarations for these identifiers are visible), and
the identifier of the pointer pfi has block scope and no linkage.
18 EXAMPLE 2 The declaration
int (*apfi[3])(int *x, int *y);
declares an array apfi of three pointers to functions returning int. Each of these functions has two
parameters that are pointers to int. The identifiers x and y are declared for descriptive purposes only and
go out of scope at the end of the declaration of apfi.
19 EXAMPLE 3 The declaration
int (*fpfi(int (*)(long), int))(int, ...);
declares a function fpfi that returns a pointer to a function returning an int. The function fpfi has two
parameters: a pointer to a function returning an int (with one parameter of type long int), and an int.
The pointer returned by fpfi points to a function that has one int parameter and accepts zero or more
additional arguments of any type.
20 EXAMPLE 4 The following prototype has a variably modified parameter.
void addscalar(int n, int m,
double a[n][n*m+300], double x);
int main()
{
double b[4][308];
addscalar(4, 2, b, 2.17);
return 0;
}
void addscalar(int n, int m,
double a[n][n*m+300], double x)
{
for (int i = 0; i < n; i++)
for (int j = 0, k = n*m+300; j < k; j++)
// a is a pointer to a VLA with n*m+300 elements
a[i][j] += x;
}
21 EXAMPLE 5 The following are all compatible function prototype declarators.
double maximum(int n, int m, double a[n][m]);
double maximum(int n, int m, double a[*][*]);
double maximum(int n, int m, double a[ ][*]);
double maximum(int n, int m, double a[ ][m]);
as are:
void f(double (* restrict a)[5]);
void f(double a[restrict][5]);
void f(double a[restrict 3][5]);
void f(double a[restrict static 3][5]);
(Note that the last declaration also specifies that the argument corresponding to a in any call to f must be a
non-null pointer to the first of at least three arrays of 5 doubles, which the others do not.)
Forward references: function definitions (6.9.1), type names (6.7.6).
6.7.6 [Type names]
1 Syntax
type-name:
specifier-qualifier-list abstract-declaratoropt
abstract-declarator:
pointer
pointeropt direct-abstract-declarator
direct-abstract-declarator:
( abstract-declarator )
direct-abstract-declaratoropt [ type-qualifier-listopt
assignment-expressionopt ]
direct-abstract-declaratoropt [ static type-qualifier-listopt
assignment-expression ]
direct-abstract-declaratoropt [ type-qualifier-list static
assignment-expression ]
direct-abstract-declaratoropt [ * ]
direct-abstract-declaratoropt ( parameter-type-listopt )
Semantics
2 In several contexts, it is necessary to specify a type. This is accomplished using a type
name, which is syntactically a declaration for a function or an object of that type that
omits the identifier.[128]
Footnote 128) As indicated by the syntax, empty parentheses in a type name are interpreted as ‘‘function with no
parameter specification’’, rather than redundant parentheses around the omitted identifier.
3 EXAMPLE The constructions
(a) int
(b) int *
(c) int *[3]
(d) int (*)[3]
(e) int (*)[*]
(f) int *()
(g) int (*)(void)
(h) int (*const [])(unsigned int, ...)
name respectively the types (a) int, (b) pointer to int, (c) array of three pointers to int, (d) pointer to an
array of three ints, (e) pointer to a variable length array of an unspecified number of ints, (f) function
with no parameter specification returning a pointer to int, (g) pointer to function with no parameters
returning an int, and (h) array of an unspecified number of constant pointers to functions, each with one
parameter that has type unsigned int and an unspecified number of other parameters, returning an
int.
6.7.7 [Type definitions]
1 Syntax
typedef-name:
identifier
Constraints
2 If a typedef name specifies a variably modified type then it shall have block scope.
Semantics
3 In a declaration whose storage-class specifier is typedef, each declarator defines an
identifier to be a typedef name that denotes the type specified for the identifier in the way
described in 6.7.5. Any array size expressions associated with variable length array
declarators are evaluated each time the declaration of the typedef name is reached in the
order of execution. A typedef declaration does not introduce a new type, only a
synonym for the type so specified. That is, in the following declarations:
typedef T type_ident;
type_ident D;