Before C23
Prior to C23, you couldn't put a label before a declaration like int coord_x;
.
You could label a block — add {
before int coord_x;
and }
before break;
(after it would work too).
C11 §6.8.1 Labeled statements shows that a label must be followed by a statement. §6.8 Statements shows what constitutes a statement; §6.8.2 Compound statements shows that declarations are different from statements, and 6.7 Declarations covers what a declaration consists of.
A label must precede a statement, but that can be a null statement — just a semicolon ;
. This means you can't put a label immediately before the closing brace of a compound statement; you must put a semicolon after it to be the labelled statement.
C23 and later
C23 lifts the constraint that you cannot label a variable declaration. The summary in (new) Annex M.2 states:
- allowed placement of labels in front of declarations and at the end of compound statement;
It achieves this by refining the syntax:
- (6.8.1) labeled-statement: label statement
- (6.8.2) compound-statement: { block-item-listopt }
- (6.8.2) block-item-list: block-item | block-item-list block-item
- (6.8.2) block-item: declaration | unlabeled-statement | label
The semantics section says:
Any statement or declaration in a compound statement may be preceded by a prefix that declares an identifier as a label name. The optional attribute specifier sequence appertains to the label. Labels in themselves do not alter the flow of control, which continues unimpeded across them.
So, in C23, a label can appear before declarations or immediately before the closing brace of a compound statement.
The 'optional attribute specifier' is primarily [[maybe_unused]]
which indicates that the label to which it is attached might not be used. The compiler is encouraged not to give warnings about the either the use or non-use of labels tagged with that attribute.