The C and C++ standards require that the compiler to ensure that get_value()
is evaluated (or at least to behave as-if it were evaluated).
So in the general case, get_value
will be evaluated. You can easily check this with godbolt:
extern int* get_value();
int func() {
if( get_value() !=NULL)
{
}
}
Produces the x86 assembly on gcc 4.4.7 as follows:
sub rsp, 8
call get_value()
add rsp, 8
ret
Note that get_value()
is called, but the != NULL check doesn't happen since that comparison is not observable. So for this compiler, you can say that a strict sense that the full comparison is not evaluated, but the comparison is not fully eliminated since get_value
must still be called (which is likely the expensive part).
The compiler is forced to take this path since it has no idea what side effects get_value
may have, so it must call it. It is free to ignore the return value since it knows that the comparison and empty if-statement body have no effect.
In one special case, however, the compiler could eliminate the entire statement - if it can prove at compile-time that the get_value
method has no side-effect. This is possible if the get_value method is declared in the same compilation unit (and perhaps also with some fancy link-time optimization).
We update the example to put the implementation of get_value inside the compilation unit, and ensure it has no side effects:
int* get_value() {
return 0;
}
int func() {
if( get_value() !=NULL)
{
}
}
Now, the method is compiled into a no-op:
func():
rep
ret
(for the function of that apparently useless rep prefix, see here...)
So it all depends on the details of get_value
, and how much the compiler can know about it when it is compiling your empty if statement.