I got the following discrepancy between compiling as 'C' vs. compiling as 'C++'
struct A {
int x;
int y;
};
struct A get() {
return {0};
}
When compiling as 'C++' everything goes fine. However, when compiling as 'C'; i am getting:
error : expected expression
which i can fix by doing:
return (struct A){0};
However, i wonder where the difference comes from. Can any one point in the language reference where this difference comes from?
As the user-defined function declaration mandates return 0, so we must utilize return 0, or return -1 within each C program. If we wouldn't directly declare a value, the assembler automatically includes a return 0; so it is optional to insert a return 0.
The reason for the error/warning message is because a void function, by definition, does not return a value. When you include the return (0) statement, you are saying that the function returns a value of 0. This presents the compiler with a contradicting declaration and return. So, the compiler generates an error.
'return 0' means that the function doesn't return any value. It is used when the void return type is used with the function. It is not mandatory to add a 'return 0' statement to the function which doesn't return any value, the compiler adds it virtually. 30th June 2019, 11:21 PM.
The two use completely different mechanisms, one of which is C++11-specific, the other of which is C99-specific.
The first bit,
struct A get() {
return {0};
}
depends on [stmt.return] (6.6.3 (2)) in C++11, which says
(...) A return statement with a braced-init-list initializes the object or reference to be returned from the function by copy-list-initialization from the specified initializer list. [ Example:
std::pair<std::string,int> f(const char *p, int x) { return {p,x}; }
-- end example ]
This passage does not exist in C (nor C++ before C++11), so the C compiler cannot handle it.
On the other hand,
struct A get() {
return (struct A){0};
}
uses a C99 feature called "compound literals" that does not exist in C++ (although some C++ compilers, notably gcc, provide it as a language extension; gcc warns about it with -pedantic). The semantics are described in detail in section 6.5.2.5 of the C99 standard; the money quote is
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. (footnote 80)
80) 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.
So in this case (struct A){0}
is an unnamed object that is copied into the return value and returned. (note that modern compilers will elide this copy, so you do not have to fear runtime overhead from it)
And there you have it, chapters and verses. Why these features exist the way they do in their respective languages may prove to be a fascinating discussion, but I fear that it is difficult for anyone outside the respective standardization committees to give an authoritative answer to the question. Both features were introduced after C and C++ split ways, and they're not developed side by side (nor would it make sense to do so). Divergence is inevitable even in small things.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With