我使用的是旧版本的Diab C编译器。
在我的代码中,我获取了一个函数名称,并将其重新定义为具有相同签名的函数指针。在进行此更改之前,代码有效。更改后,它导致嵌入式系统锁定。
函数指针在头文件中声明为extern,在一个.c文件中定义,并在另一个.c文件中使用。当从第二个.c文件调用它时,它将导致系统锁定。当我尝试使用sprintf添加调试信息时,它最终告诉我它是一个未定义的符号。我意识到头文件没有包含在第二个.c文件中。当我#included它编译并正常工作时。
我的问题是,是否有一些C规则允许编译器推断出函数签名,即使在调用位置未定义符号?根据我的理解,在我做出任何改动之前很久就会出现错误。
答案 0 :(得分:1)
如果没有可用的声明,则编译器使用函数的默认声明来获取未知数量的参数并返回int。如果你打开编译器警告(例如-Wall -Wextra -Werror
和gcc,请查看编译器的文档),你应该得到一个编译时警告。
答案 1 :(得分:1)
最有可能的是,代码最初起作用的原因是它是在C89或类似模式下编译的。 1989年的C标准允许在没有首先声明它们的情况下调用函数。
当您更改代码以使用指针但未包含指针声明时,编译器假定您的指针实际上是一个函数并生成代码以调用指针,就像指针具有可执行代码一样内。结果,程序可以理解地停止了工作。
你应该做的是启用所有可能的警告(对于gcc:-Wall
,-Wextra
并确保启用优化(-O2
是好的),因为它启用了代码分析),尤其是用于调用没有原型的函数。更好的方法是将编译器切换到C99模式(gcc中为-std=c99
)或切换到C99编译器。 1999年的C标准禁止在没有原型的情况下调用函数,并且在C89中没有一些有用的功能。