C While循环使用未定义的函数&x27;s名称作为条件

C While循环使用未定义的函数&x27;s名称作为条件,c,gcc,C,Gcc,这段代码为什么运行 #include <stdio.h> int i(); int main(){ while(i){printf("Hi");} } #包括 int i(); int main(){ 而(i){printf(“Hi”);} } while循环接受的i的值到底是多少 我尝试了printf(“%d”,I),它说I是未定义的,这是预期的,因为它只有声明,但为什么在工作时会起作用?如果在启用适当警告的情况下编译,您将看到 warning: the address

这段代码为什么运行

#include <stdio.h>
int i();
int main(){
    while(i){printf("Hi");}
}
#包括
int i();
int main(){
而(i){printf(“Hi”);}
}
while循环接受的i的值到底是多少


我尝试了
printf(“%d”,I)
,它说
I
是未定义的,这是预期的,因为它只有声明,但为什么
工作时会起作用?

如果在启用适当警告的情况下编译,您将看到

warning: the address of ‘i’ will always evaluate as ‘true’ [-Waddress]
     while(i){printf("Hi\n");}
这里,
i
的值作为函数的地址,即函数指针

要添加更多上下文,请从(我的重点)

-Waddress

对内存地址的可疑使用发出警告。其中包括在条件表达式中使用函数的地址,例如
void func(void);if(func)
以及与字符串文本的内存地址的比较,例如
if(x==“abc”)
这种用法通常表示程序员错误:函数的地址总是计算为true,因此在条件语句中使用它们通常表示程序员忘记了函数调用中的括号和与字符串文本的比较会导致未指定的行为,并且在C中不可移植,因此它们通常表示程序员打算使用
strcmp
。此警告由
-Wall
启用


您有函数声明
inti()

C11标准(n1570)规定:

函数指示符是具有函数类型的表达式。除非它是
sizeof
运算符、
\u Alignof
运算符或一元
&
运算符的操作数,否则类型为“函数返回类型”的函数指示符将转换为类型为“指向函数返回类型的指针”的表达式。


因此,
中的
i
,而(i)
是指向函数的指针,由于它是一个地址,它的计算结果将始终为true

i
本身计算为函数的地址,即真值。由于您从不调用函数或将值用于除true或false以外的任何对象,编译器可以优化并忽略函数未定义的事实。另一个问题是
printf(“%d”,i)
调用UB,因为您只能使用
%d
打印
int
s,这是否意味着即使未定义函数,函数地址也被视为非空?对于未定义的标识符,我希望得到与作者在打印
I
时相同的链接器错误。我认为这是实现定义的,或者超出了C标准。例如,使用
gcc
\uuuuu attribute\uuuuu((\uuuu-weak\uuuu))int i()
在链接期间未找到函数声明的情况下,地址将计算为NULL。它涉及函数参数,不是吗?