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(関数ポインタ)は意味のあるコードです。
参考:
■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ポインタ参照が発生するのでこの様なコードは避けましょう。