【C言語】
if(関数名!=0)はif(関数名()!=0)とは違う

warning: the address of ‘func’ will always evaluate as ‘true’

警告:アドレスの無い関数は無い
[-Waddress]

■この記事の概要

C言語での条件文における典型的なミス、
if(関数名)とif(関数名())の違いを解説。

関数アドレスの評価がtrueとなる理由を紹介しています。


■if(関数名)は必ず成立

#include <stdio.h>
int my_func(void){
    puts("my_func");
    return  0;
}
int main(void){
    if(my_func){ 
        puts("間違い➡常に成立");
    }
    if(my_func != 0){ 
        puts("間違い➡常に成立");
    }
    if(my_func() != 0){ 
        puts("戻り値により成立");
    }
}
gcc -Wall f1.c
f1.c: In function ‘main’:
f1.c:7:8: warning: the address of ‘my_func’ will always evaluate as ‘true’ [-Waddress]
    7 |     if(my_func){
      |        ^~~~~~~
f1.c:10:16: warning: the comparison will always evaluate as ‘true’ for the address of ‘my_func’ will never be NULL [-Waddress]
   10 |     if(my_func != 0){
./a.out
間違い➡常に成立
間違い➡常に成立
my_func

if(func)ではなくて
if(func())の誤りでしょう。

if(func)は
if(関数funcのアドレス) の意味なので常に成立します。

尚、関数ポインタはNULLになる事があるので
if(関数ポインタ)は意味のあるコードです。

参考:

EXP16-C. 関数ポインタを定数値と比較しない


■if(配列名 == NULL)は必ず不成立

//warning: comparison of array 'buf' equal to a null pointer is always false 
//[-Wtautological-pointer-compare]
#include <stdio.h>
int main(void){
    char buf[BUFSIZ] = {0};
    while(fgets(buf,BUFSIZ,stdin) != NULL){
        if(buf == NULL){//間違い➡常に不成立
            puts("ここには来ない");
            continue ;
        }        
        if(buf[0] == '\n'){
            puts("空行");
            continue;
        }
        printf("有効入力➡%s",buf);
    }
}
clang  -Wall -Wextra f2.c
f2.c:7:12: warning: comparison of array 'buf' equal to a null pointer is always false [-Wtautological-pointer-compare]
        if(buf == NULL){//間違い➡常に不成立

アドレスの無い変数や配列はありません。
変数や配列には必ずアドレスがあるので、
変数や配列のアドレスの有無を判定するif文は意味がありません。


未定義の動作の結果はわからない

//未定義動作 clang bug.c -fsanitize=undefined
#include <stdio.h>
typedef struct {
	char ary[1024];
} tag ;
void func(tag *p){
	if (p->ary == NULL) {
		puts("アドレスが無い!?");
	}else{
        puts("アドレスが有る");
    }
}
int main(void){
	tag x ={0};
    func(&x);   //有効ポインタ
    func(NULL); //NULLポインタ➡未定義動作
}
clang   -Wall -Wextra bug.c -fsanitize=undefined
bug.c:7:9: warning: comparison of array 'p->ary' equal to a null pointer is always false [-Wtautological-pointer-compare]
        if (p->ary == NULL) {
            ~~~^~~    ~~~~
1 warning generated.
./a.out
アドレスが有る
bug.c:7:9: runtime error: member access within null pointer of type 'tag'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior bug.c:7:9 in
アドレスが無い!?

if(配列名 == NULL)は必ず不成立なのですが、
未定義動作の時は成立してしまう場合があります。上記の場合NULLポインタ参照が発生するのでこの様なコードは避けましょう。