如何在C语言中检查头文件的有效性

如何在C语言中检查头文件的有效性,c,file,header,C,File,Header,在C编程语言中是否有一种方法可以检查头文件中的函数原型是否与编译时的实际函数定义相对应。 例如,如果我创建了头文件,然后更改了该头文件中描述的某个函数的签名,我是否可以在编译时检查头文件中是否有错误的原型?在编译之前,这是编译器的工作还是其他工具的工作? 谢谢。这是编译器的工作,根据我的经验,它做得很好:) 如果头文件中的函数原型与源文件中的定义不匹配,则无法在其他源文件中使用该函数,因为未声明该函数,编译器将通过给出错误来通知您。如果您使用两个不同的原型声明相同的函数名,编译器应捕捉到这一点,

在C编程语言中是否有一种方法可以检查头文件中的函数原型是否与编译时的实际函数定义相对应。 例如,如果我创建了头文件,然后更改了该头文件中描述的某个函数的签名,我是否可以在编译时检查头文件中是否有错误的原型?在编译之前,这是编译器的工作还是其他工具的工作?
谢谢。

这是编译器的工作,根据我的经验,它做得很好:)


如果头文件中的函数原型与源文件中的定义不匹配,则无法在其他源文件中使用该函数,因为未声明该函数,编译器将通过给出错误来通知您。

如果您使用两个不同的原型声明相同的函数名,编译器应捕捉到这一点,即:

int foo(int a, int b);

...

int foo(int a, float b) { ... }
当然,如果您确实重命名了函数,则编译器无法捕获它,即:

int foo(int a, int b);

...

int fee(int a, int b) { ... }

当然,除非您试图从其他地方调用
foo
。然后链接器会抱怨。

如果您使用该函数,如果原型的实现不存在,编译器会给您一个链接器错误。但是,如果您从未使用该函数(例如,在构建库时),链接器将不会抱怨

这是您应该确保在测试中有良好的代码覆盖率的原因之一-例如,如果您有一些单元测试也被编译,链接器会抱怨。如果您有一些无法测试且不会从代码中被调用的函数,您可以编写一个虚拟可执行文件(不必工作),它将调用所有这些函数


最后一种解决方案是使用clang库编写自己的代码检查器。

您的函数是在编译的其他源代码中还是在库中?如果您自己在这里编译它们,那么当您使用不同的签名编译函数定义时,应该会出现错误。所以,我的头文件带有错误的函数签名,并且已经编译了该函数的源文件。当我编译包含头文件的其他源文件时,编译器会抱怨吗?在编译时:否-编译器会相信头文件对于新代码是正确的。根据您的系统,在某些情况下,您可能会在链接时出错,例如,在Windows上,如果您使用的是u stdcall调用约定,则参数的字节数包含在生成的符号中(例如_strcpy@8)因此,如果签名中的参数数量已更改,则会出现链接器错误。谢谢您的回答,所以基本上,要检查头文件函数签名是否与源代码文件中的实际签名相同,编译器必须在编译时具有可用的源代码,以便将其与头文件进行比较。如果在编译某个源文件时包含某个头文件,而该头文件在编译时不可用,编译器应该抱怨吗?@Vladimir Radojicic:如果源文件包含一个不存在的头文件,那么编译器将给出一个错误,即它找不到特定的头文件。我的意思是头文件中某些函数的实现的源代码不存在,不是头文件本身。@Vladimir Radojicic:这将导致编译,但由于函数定义不存在,它将给您一个链接错误;这个函数的实现是intfoo(inta,float b){…},例如错了。当我编译一些包含这个头文件的源代码时,如果当时编译器只有包含头文件和头文件的源代码,而没有头文件函数实现的源代码,那么它能捕捉到错误吗?@Vladimir:编译器应该给你一个错误,上面写着“foo的类型冲突”(或诸如此类)当您使用
foo
的实现编译源文件时,它不会对任何其他源文件发出警告。但是如果您更改了头文件,您的生成系统也应该尝试重新编译实现源文件!因此,当我编译不包含foo实现的其他源文件时,但是它只是包含了带有错误签名的头文件,foo编译器不会给出任何警告。但是它有自动机制来检查头文件和实现文件中函数原型的差异?@Vladimir:没错。但是就像我说的,你的构建系统应该为你处理这个问题。