Function Call Warning

I read "C ++ Programming Language - Fourth Edition", and I was typing a simple exercise to get the C ++ syntax, and I accidentally stumbled upon something that made me raise an eyebrow. In short, I forgot to add () to accept basically:

 bool accept() { cout << "Do you want to proceed (y or n)?\n"; char answer = 0; cin >> answer; if (answer == 'y') { return true; } return false; } int main() { accept; } 

Executes and compiles and produces (in VS2015)

C4551 - List of Missing Function Arguments

I found that I read lambdas and a bunch of questions about SO that should be closed, because they basically ask for "debug my code".

I realized that if the code compiles and runs, and the function contains a lock statement (waiting for user input) and the type of the return value, then all the code will be executed as expected, regardless of the absence of parentheses; this is not true.

In addition, I decided that I would change the call to accept in the main, to bool a = accept; cout << a; bool a = accept; cout << a; to try to prevent any optimization (if that was what was actually happening), and that did not call the accept() code either,

What I am interested to know:

  • What causes the accept call compiled in?
  • Why the accept code is not called
  • Why is this just a warning and not an error (I know that I can change the configuration to display it as an error, I doubt more how it is accepted in the default syntax when the actual result differs from the expected result so “sharply?” This question may be based on opinions, omit it if you agree with it.)
  • Code execution bool a = accept; cout << a; bool a = accept; cout << a; in the main expression outputs 1 as output. How can this be when false is the default bool default value (at least in C #) and there is nothing to return the true value since the acceptance code is not executed?
+6
source share
2 answers
  • There is no response to accept . "See No. 3.

  • Because of # 1.

  • Using the function name without the function call syntax (i.e.: () ) means that you are accessing the function itself. For example, you can save it in a function pointer (via function-to-pointer decomposition):

     using my_func = bool(*)(); //Function that takes nothing and returns a bool. my_func var = accept; //Store a pointer to `accept`. 

    Then you can issue var(); which will call accept .

    However, since you never store a function, the compiler guesses that you probably wanted to call the function, and not to access the function pointer. accept; however, it is a legitimate C ++ operator, so the compiler cannot make a mistake on it. It may issue a warning because the statement does nothing, and you probably wanted to call a function. This is no different from a type 1; statement 1; : completely legal, but completely useless.

  • He does this because of the C ++ trick. Non-empty pointers break into a boolean true . And accept splits into a function pointer that is not null. Therefore, when converting to bool it will be true . You are still not calling the function.

+14
source

In C ++, any expression followed by a semicolon is a legal statement. (Why? Because C will allow you to do this, I think). This means that all of the following legal statements:

  5; 3 + 5; 1 % 2 == 0; 

The effect of an expression of this form is that the expression is evaluated and then discarded. A good optimizing compiler will simply eliminate all the logic here, since none of them have side effects.

In your case, write

 accept; 

is a legal statement because accept is an expression evaluating a reference to the accept function. This means accept; as an operator means "evaluate the accept address and then discard it." The reason no function is called here is because the name of the function itself does not call the function; you need parentheses (function call statement) for the actual call. This is useful, for example, if you want to pass a function to another function. For example, you can pass the comparison function to std::sort , for example:

 std::sort(range.begin(), range.end(), nameOfMyComparisonFunction) 

It would be a real problem if this would cause a nameOfMyComparisonFunction call, since the arguments cannot be known until the sorting procedure begins.

So why is this a warning and not an error? Well, this is perfectly legitimate C ++ code, so the compiler cannot properly call it an error. However, the compiler has the right to flag this as a warning, as it almost certainly means that you made a mistake. However, most compilers have some setting that warns of warnings as errors, and if you raise the warning level high enough, the compiler will probably say: "This is so suspicious that I'm going to assume that you messed up something."

As for your last - why

 bool a = accept; 

end up a to true? In C ++, any non-bubble pointer is implicitly converted to true, and any null pointer is implicitly converted to false. In C ++, functions are implicitly converted to pointers to themselves, so in this case, accept evaluates the address of the accept function, which is not zero, therefore sets a to true . When you write

 cout << a << endl; 

the value prints as 1 since bool values ​​print as 1 and 0, not true and false by default. However, you can write

 cout << boolalpha << a << endl; 

and instead you will see true .

Hope this helps!

+8
source

All Articles