3

I was wondering why both versions of this code have no error:

#include <iostream>

bool check_number(int n) {
    return n < 5;
}

int main() {
    int number = 6;

    // (1) prints "Hello World"
    if (check_number)
    // (2) prints "not hello world"
    if (check_number(number))
    {
        std::cout << "Hello world!";
    }
    else
    {
        std::cout << "not hello world";
    }

    return 0;
}

Condition (1) prints Hello world! despite the fact that I have not passed the variable number into the function check_number in the if-statement.

In case (2), I get not hello world as expected.

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Freddie99
  • 49
  • 2

4 Answers4

9

if (check_number) { is just checking the value of the function pointer against nullptr (or 0 and other null pointer constants), which is always going to be true. It is not calling the function.

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
  • 1
    It would be better to say that it's checking whether `check_number` is a null pointer. Checking against zero is indirectly doing the same, but it's a weird way of phrasing it. – Jan Schultke Jul 13 '23 at 12:45
  • @JanSchultke Makes sense. Answer edited. – Jesper Juhl Jul 13 '23 at 13:03
  • 1
    I've corrected it, because `false` is not a null pointer constant, so it wouldn't be possible to compare `check_number == false`. – Jan Schultke Jul 13 '23 at 13:13
5
if (check_number)

In this context check_number decays to a function pointer, and as the former has an address, the latter is not the null pointer, thus the test succeeds and you enter the if branch.

That's just the same as if you assign the function to a function pointer without explicitly taking the address of:

bool(*fPtr)(int) = check_number; // don't need &check_number
Aconcagua
  • 24,880
  • 4
  • 34
  • 59
  • 1
    Would any one explain the down-vote? – Aconcagua Jul 13 '23 at 12:40
  • 2
    Spite and competition. The answer is fine. – Jan Schultke Jul 13 '23 at 12:41
  • Don't know why someone would down-vote your correct answer - but I gave you an up-vote to compensate. – Jesper Juhl Jul 13 '23 at 13:05
  • @JesperJuhl Thanks... Just received another DV [here](https://stackoverflow.com/questions/58319928/why-is-operator-removed-in-c20-for-many-standard-library-types) – seems pretty much as someone picked me as his target, so I'll probably have to face further meaningless DV :( – Aconcagua Jul 13 '23 at 16:16
5

From the C++ 17 Standard (7.3 Function-to-pointer conversion)

1 An lvalue of function type T can be converted to a prvalue of type “pointer to T”. The result is a pointer to the function.

and (7.14 Boolean conversions)

1 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. For direct-initialization (11.6), a prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.

So in the expression of the if statement

if (check_number) {

the function designator is implicitly converted to a pointer to the function and as it is not a null pointer then the expression evaluates to true.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

You can infer that the condition (check_number) does not involve a function call because no argument is passed, as you aptly observed.

So in what way can this be valid and behave as a true (i.e. nonzero) condition ?

Just by the fact that a function name alone, the same way as an array name alone, is turned to a pointer (to function or to array).

Yves Daoust
  • 672
  • 9