5

I dont undestand this statement: f().array;... is a function call? or an access an attribute of the class? The statement data f(); is constructor's call? that's right?

#include <iostream>
using namespace std;

void f()
{
    cout << "hello!" << endl;
}

struct data 
{ 
    int array[10]; 
};

int main()
{
    data f();

    f().array;

    return 0 ;
}
user3793107
  • 135
  • 1
  • 1
  • 3
  • `data f();` is a function declaration. – chris Jul 29 '14 at 14:04
  • Try to compile it and see. – juanchopanza Jul 29 '14 at 14:05
  • [Most vexing parse](http://stackoverflow.com/questions/1424510/most-vexing-parse-why-doesnt-a-a-work) – dlf Jul 29 '14 at 14:05
  • 6
    How on earth does GCC manage to compile this without even a single diagnostic? `void f()` and `data f()` don't have compatible type, and clang rejects it with a hard error. –  Jul 29 '14 at 14:06
  • 2
    @hvd it even runs for me. Prints `hello!` – FDinoff Jul 29 '14 at 14:09
  • 1
    @hvd, I am also quite puzzled by this, even with `-Wall -Wextra -pedantic` `g++` does not spit any error. `clang++` doesn't compile it on my side either. – vsoftco Jul 29 '14 at 14:16
  • @hvd, actually it allows just the declaration. If you try to define `data f()` after `main()` it complains of course. Strange. – vsoftco Jul 29 '14 at 14:19
  • 2
    I don't understand all the down-votes, this seems to be a reasonable question, and I would love to have someone explains why `f().array` compiles under `g++` and prints `hello!`. So it calls the `void f()`, then thinks that you actually called `data f()`, and finally access its member `array`? This is preposterous, and `clang` is not accepting this code (cannot overload by return type). Of course the reason of getting into this whole mess is the most vexing parse, but still this is a good question in my opinion. – vsoftco Jul 29 '14 at 14:25
  • @vsoftco: Look at it this way. In g++'s eyes, `f()` is a function that returns data. Now, the actual implementation of that function isn't going to put anything there, so the return value is going to be some screwed up value. We then add an offset (of 0) to that value to find the location of `f().array`. We then don't actually read or write any of it, so nothing in the generated code causes a fault. – Bill Lynch Jul 29 '14 at 14:27
  • 1
    @sharth, I know that `f()` returns a data (at least the version defined in `main`). My question is: why does it print `hello!` under `g++`? It seems that `void f()` is called. And one should not be able to compile this code at all, since you overload by return type. – vsoftco Jul 29 '14 at 14:30
  • Why does it compile? Well the compiler just checks the syntax and if there is a problem it will output an error message. Even though there is no error at compile time, the error can occur at run time. Some errors might not be detected until the program is executed. – Juniar Jul 29 '14 at 17:15

2 Answers2

5

The void f() and following lines define a function, f which takes parameters and return nothing.

The line data f(); declares a function f, which takes no parameters but return an object of type data. Since we've already seen the definition of f, we know that this line is actually lying to us, but the compiler lets it lie, because it wants to remain compatible with C where the definition could have been the one who's lying.

Got that?

UPDATE:

Originally, C didn't have the void keyword. So, to say that f() didn't return anything, you just left off the return type -- except the designers were lazy typists, so they decided to actually make "type not specified" mean "default to int" because they were returning ints more often than nothing. So, f() could be defining a function which returned nothing or an int. I think compilers were actually cool with you writing something like if (x==1) return 5; else return "five"; and letting the calling function figure out the return value.

Which brings us to data f();. Since you've just told the compiler that f() returns a data object, it trusts you, and ignores what you told it before. Of course, after the main() function, the new declaration of f() goes out of scope, and the compiler goes back to using the original signature for f().

The bottom line is, while legal, which is VERY BAD CODE (tm), and whoever wrote it should be slapped.

James Curran
  • 101,701
  • 37
  • 181
  • 258
  • 1
    I asked this above (in the comments), but will ask again, can you explain why it first print `hello` (so `void f()` is invoked`, then behaves like you'd called `data f()` and let access its member `array`? At least this is what happens under `g++` – vsoftco Jul 29 '14 at 14:51
1

I dont undestand this statement: f().array;... is a function call? or an access an attribute of the class?

Both. It calls the function f, then accesses the return value's array member (but does nothing with it, making the member access pointless).

The statement data f(); is constructor's call?

No, it's a function declaration. In this case, it should give an error because you've already declared f with void return type.

To declare an object, you want:

data f;          // default-initialisation: leaves the array uninitialised
data f{};        // value-initialisation (since C++11): zero-initialise the array
data f = data(); // value-initialisation (historic): zero-initialise the array
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644