4 ms·
Several of the examples shown as valid C are not. For example, this: const int foo = 1; int* bar = &foo; *bar = 2; is said to have undefined beha
by _kst_ 7y ago
Several of the examples shown as valid C are not.
For example, this:
const int foo = 1;
int* bar = &foo;
*bar = 2;
is said to have undefined behavior, but in fact the initialization of `bar` is a constraint violation, requiring a diagnostic. (Some compilers will issue a non-fatal warning, which is allowed by the C standard but IMHO is unfortunate.)
Another example: it says that this:
const size_t buffer_size = 5;
int buffer[buffer_size];
will not compile in C, but it's valid at block scope in C99, which introduced variable-length arrays. (C11 made them optional.)
"In C, this would compile, albeit likely with warnings about implicit conversion:"
int main() {
auto x = "actually an int";
return x;
}
The "implicit int" rule was dropped in C99, and even before that the language did not define an implicit conversion from char* to int. Again, some compilers might support it with a warning, but it's a constraint violation.
- lochsh 7y agoThanks, this is useful! I'll have to look at the standards again and be more precise in my language.
- klingonopera 7y ago> Some compilers will issue a non-fatal warning, which is allowed by the C standard but IMHO is unfortunate. GCC 5.1.0 reports: warning: initialization discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers]
- lochsh 7y agoI haven't been able to find anything in the C11 standard about the initialisation of bar being a constraint violation. In 6.7.3, the only constraints for type qualifiers listed are for _Atomic and restrict. Could you let me know where you got the information you talk about here from? I could be missing part of the standard.
- _kst_ 7y agoN1570 6.7.9p11 says that the constraints and conversions for simple assignment apply to scalar initializers. 6.5.16.1p1 says that, for pointers, "the type pointed to by the left has all the qualifiers of the type pointed to by the right". In this case, the right operand is a pointer to a const-qualified type and the left operand is a pointer to a non-const-qualified type. (Without this restriction, you could silently discard const qualification just by assigning or initializing a pointer, which would largely defeat the purpose of const.)