Citations are from N1570 (C11 draft). I don't think there are any
relevant differences in other editions or drafts of the standard.
Quick summary: Why is
int n = {{0}};
undefined behavior rather than a constraint violation?
6.7.9 (Initialization) includes a list of constraints, starting with "No initializer shall attempt to provide a value for an object not contained within the entity being initialized."
6.7.9p11 says:
The initializer for a scalar shall be a single expression,
optionally enclosed in braces. The initial value of the object is
that of the expression (after conversion); the same type constraints
and conversions as for simple assignment apply, taking the type of
the scalar to be the unqualified version of its declared type.
(I presume that "optionally enclosed in braces" is not intended to permit more than one level of braces.)
Both
int n = 0;
and
int n = {0};
are clearly valid, with identical semantics. But this:
int n = {{0}};
violates that requirement. Since the requirement is under Semantics,
not Constraints, code that violates it has undefined behavior. Starting
with C99, this is mentioned in Annex J.
My question: Why is this undefined behavior rather than a constraint violation?
I suggest that moving that paragraph from Semantics to Constraints would
be an improvement. Extra braces on a scalar initializer are easy to
detect, and requiring a diagnostic should not be a significant burden,
and would promote consistency. (Alternatively, the standard could have explicitly allowed arbitrarily nested braces.)
With the current requirements, a compiler could quietly generate code to
set n to 42, though I doubt that anyone would do that.
(I note that gcc issues a non-fatal warning with "-std=c17
-pedantic-errors", while clang treats it as a fatal error.)
Citations are from N1570 (C11 draft). I don't think there are any
relevant differences in other editions or drafts of the standard.
Quick summary: Why is
int n = {{0}};
undefined behavior rather than a constraint violation?
6.7.9 (Initialization) includes a list of constraints, starting
with "No initializer shall attempt to provide a value for an
object not contained within the entity being initialized."
6.7.9p11 says:
The initializer for a scalar shall be a single expression,
optionally enclosed in braces. The initial value of the
object is that of the expression (after conversion); the same
type constraints and conversions as for simple assignment
apply, taking the type of the scalar to be the unqualified
version of its declared type.
(I presume that "optionally enclosed in braces" is not intended to
permit more than one level of braces.)
Both
int n = 0;
and
int n = {0};
are clearly valid, with identical semantics. But this:
int n = {{0}};
violates that requirement. Since the requirement is under
Semantics, not Constraints, code that violates it has undefined
behavior. Starting with C99, this is mentioned in Annex J.
My question: Why is this undefined behavior rather than a
constraint violation?
I suggest that moving that paragraph from Semantics to Constraints
would be an improvement. Extra braces on a scalar initializer are
easy to detect,
and requiring a diagnostic should not be a significant burden,
and would promote consistency. [...]
With the current requirements, a compiler could quietly generate
code to set n to 42, though I doubt that anyone would do that.
(I note that gcc issues a non-fatal warning with "-std=c17
-pedantic-errors", while clang treats it as a fatal error.)
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Citations are from N1570 (C11 draft). I don't think there are any
relevant differences in other editions or drafts of the standard.
Quick summary: Why is
int n = {{0}};
undefined behavior rather than a constraint violation?
Because there is no practical benefit to changing what the
standard says now.
There's no practical benefit to changing it. The current rule
has been in place since the original ANSI C standard, more than
30 years ago. Whatever the motivation may have been at that
time, there is no incentive to change the rules now; compilers
already give diagnostics in such cases, even though they don't
have to. Changing the rules would mean throwing away a degree
of freedom with no significant benefit.
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
Citations are from N1570 (C11 draft). I don't think there are any
relevant differences in other editions or drafts of the standard.
Quick summary: Why is
int n = {{0}};
undefined behavior rather than a constraint violation?
Because there is no practical benefit to changing what the
standard says now.
Do you have an opinion about whether it should have been specified as a constraint violation rather than undefined behavior in the first place?
There's no practical benefit to changing it. The current rule
has been in place since the original ANSI C standard, more than
30 years ago. Whatever the motivation may have been at that
time, there is no incentive to change the rules now; compilers
already give diagnostics in such cases, even though they don't
have to. Changing the rules would mean throwing away a degree
of freedom with no significant benefit.
It would remove a degree of freedom for implementers, one that
few if any currently take advantage of.
Meaningless degrees of freedom for implementers do not help
users.
Sysop: | DaiTengu |
---|---|
Location: | Appleton, WI |
Users: | 1,030 |
Nodes: | 10 (1 / 9) |
Uptime: | 56:26:45 |
Calls: | 13,349 |
Calls today: | 1 |
Files: | 186,574 |
D/L today: |
296 files (71,549K bytes) |
Messages: | 3,358,461 |