Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

return {0} from a function in C?

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?

like image 572
sramij Avatar asked Jan 11 '15 12:01

sramij


People also ask

Do you write return 0 in C?

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.

Can you return 0 in a void function C?

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.

What does it mean to return 0?

'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.


1 Answers

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.

like image 60
Wintermute Avatar answered Oct 12 '22 21:10

Wintermute