Is { struct-declaration-list }
in C11 (as known as { member-declaration-list }
in C23) a block?
The original issue: I cannot find the exact definition of the term "block" in the C standard (C11, C23).
For example: C11 prescribes that:
A compound statement is a block.
and defines the compound statement as:
compound-statement:
{ block-item-listopt }
The { struct-declaration-list }
may look similar to { block-item-listopt }
(i.e. "something" which is eclosed in between the {
and }
). However, I cannot find the proof or disproof that { struct-declaration-list }
is a block.
GNU C Language Manual says that (emphases added):
A block is a construct that contains multiple statements of any kind. It begins with ‘{’ and ends with ‘}’, and has a series of statements and declarations in between. Another name for blocks is compound statements.
So, it first says "statements" and second says "statements and declarations". Confused.
Wikipedia says that (emphasis added):
In computer programming, a block or code block or block of code is a lexical structure of source code which is grouped together.
and then says:
In C, blocks are delimited by curly braces - "{" and "}".
So, per Wikipedia the { struct-declaration-list }
is a block.
Is { struct-declaration-list }
in C11 (as known as { member-declaration-list }
in C23) a block?
The original issue: I cannot find the exact definition of the term "block" in the C standard (C11, C23).
For example: C11 prescribes that:
A compound statement is a block.
and defines the compound statement as:
compound-statement:
{ block-item-listopt }
The { struct-declaration-list }
may look similar to { block-item-listopt }
(i.e. "something" which is eclosed in between the {
and }
). However, I cannot find the proof or disproof that { struct-declaration-list }
is a block.
GNU C Language Manual says that (emphases added):
A block is a construct that contains multiple statements of any kind. It begins with ‘{’ and ends with ‘}’, and has a series of statements and declarations in between. Another name for blocks is compound statements.
So, it first says "statements" and second says "statements and declarations". Confused.
Wikipedia says that (emphasis added):
In computer programming, a block or code block or block of code is a lexical structure of source code which is grouped together.
and then says:
In C, blocks are delimited by curly braces - "{" and "}".
So, per Wikipedia the { struct-declaration-list }
is a block.
- Is "block" even a formal term? I think compound statement is the formal term. Which can be used to form blocks. – Lundin Commented Mar 20 at 12:13
- 2 @Lundin: “Block” is a formal term, defined, using italics to denote a definition, in C 2024 6.8.1. – Eric Postpischil Commented Mar 20 at 12:44
4 Answers
Reset to default 5A struct-declaration-list or member-declaration-list is not a block.
C 2011 specifies blocks in clause 6.8, “Statements and blocks.” It says blocks are:
- a compound statement,
- a selection statement (
if
,if … else
, andswitch
), - each associated substatement of a selection statement,
- an iteration statement (
while
,do … while
, andfor
), and - the body of an iteration statement.
The above includes the body of a function definition since it is a compound statement.
C 2024 also specifies blocks in clause 6.8 but specifies most of them in the formal grammar. The natural language text says a block is a primary block, a secondary block, or the block associated with a function definition. The first two refer to the primary-block and secondary-block grammar tokens. The primary-block token includes compound-statement, selection-statement, and iteration-statement. In the grammar for each of those statements, the secondary-block token appears as each of their substatements. The compound-statement of a function definition does not pass through the primary-block token but is a block due to the natural language statement. So the blocks in C 2024 are the same as in C 2011.
A block is either a primary block, a secondary block, or the block associated with a function definition;…
None of these is a struct-declaration-list or member-declaration-list. (While the same sequence of some tokens could, in isolation, be either a struct-declaration-list or a compound-statement, a token sequence that passes through the struct-declaration-list or member-declaration-list token, when parsing a full translation unit, does not pass through any of the tokens or statements designated as blocks.) Further, it would be impossible for a struct-declaration-list or member-declaration-list to be a block as then the member names declared in it would be out of scope after the list, making it impossible to refer to members of structures or unions.
(Note the parameters for a function definition are declared outside the block that is the function body but are associated with the block’s scope by C 2024 6.2.1.)
Sort of, but not really.
Here are the relevant parts of the language for compound statement:
compound-statement:
{ block-item-list_opt }
block-item-list:
block-item
block-item-list block-item
block-item:
declaration
statement
6.7
declaration:
declaration-specifiers init-declarator-list_opt ;
...
declaration-specifiers:
storage-class-specifier declaration-specifiers_opt
type-specifier declaration-specifiers_opt
...
type-specifier:
void
char
...
init-declarator-list
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator
declarator = initializer
6.7.6
declarator:
pointer_opt direct-declarator
direct-declarator:
identifier
...
So if you have
{
char foo;
}
...that is a member of the language defined by compound-statement, via the following series of reductions:
declaration-specifiers <- type-specifier <- "char"
init-declarator-list <- init-declarator <- identifier <- "foo"
block-item-list <- block-item <- declaration <- declaration-specifiers init-declarator-list ;
compound-statement <- "{" block-item-list "}"
However, it's also a member of struct-declaration-list, so you have a reduce/reduce conflict, and thus we need to take the context into account to resolve it. There's no parse in which "struct" compound-statement
will parse successfully, so the conflict must be resolved in favor of struct-declaration-list when preceded by "struct".
struct foobar {
int a;
double b;
};
This is not a block, because:
It contains declarations, not statements.
It does not control execution flow.
It does not introduce a new scope for variables like a block does.
{
int x = 5;
printf("%d\n", x);
}
While in C, a block is defined as a sequence of statements enclosed in curly braces {}
. It introduces a new scope and is typically used in function bodies, loops, and conditional statements.
GNU C Language Manual [...] first says "statements" and second says "statements and declarations". Confused.
The GNU C Language Manual should not be taken to provide a technical specification of the C language -- neither of any version of ISO C nor of any version of GNU C. Nor even of GNU extensions alone. Its authors have taken the liberty of using somewhat loose language.
Nor does its terminology align perfectly with that of the ISO C language spec. Although it is fairly conventional to identify the term "block" with what ISO C calls a "compound statement", the ISO C spec uses a broader definition of the former.
Aligning the terminology and text of your excerpt with the language spec would yield something more like this:
A compound statement is a statement that contains zero or more declarations and / or other statements. It begins with ‘{’ and ends with ‘}’, with all its constituent statements and declarations between.
Note that the term "block" is not used. It would be valid to add "A compound statement is a block", but that could be misleading. If you want to associate the above with the C spec's concept of block, then this might be a good way to do it:
A compound statement is one kind of block.
Wikipedia says that (emphasis added):
In computer programming, a block or code block or block of code is a lexical structure of source code which is grouped together.
This is a conventional terminology, yes.
and then says:
In C, blocks are delimited by curly braces - "{" and "}".
Yes.
So, per Wikipedia the { struct-declaration-list } is a block.
No, that does not follow. That blocks in C are delimited by curly braces does not imply that everything delimited delimited by curly braces is a block. Compare "Stack Overflow members named 'pmor' are people inclined to ask language lawyer questions", which I take to be true. It does not follow that all people inclined to ask language lawyer questions are Stack Overflow members named 'pmor'.
Moreover, Wikipedia's sense of the word "block" -- though fairly common -- is not the same as that of the C language spec.
Is
{ struct-declaration-list }
in C11 (as known as{ member-declaration-list }
in C23) a block?
If, in the course of parsing C source code according to one of the C formal grammars presented in a version of the language spec, you reduce a token sequence according to one of those productions as they appear in their respective grammars, then that token sequence is not the token sequence of a block in the language spec's sense of the term. Another answer goes into detail on what that term means in the language spec's context, and where you can find that.
Furthermore, I think that if you polled C developers then you would get mixed opinions of whether that part of a struct declaration constitutes a "block" in their own, colloquial, sense of the term. Such is human language.