如何在头文件中定义函数?
How do you define functions in header files?
设置
如果我有这样的程序
一个头文件,它声明了我的主要库函数 primary()
并定义了一个简短的辅助函数 helper()
。
/* primary_header.h */
#ifndef _PRIMARY_HEADER_H
#define _PRIMARY_HEADER_H
#include <stdio.h>
/* Forward declare the primary workhorse function */
void primary();
/* Also define a helper function */
void helper()
{
printf("I'm a helper function and I helped!\n");
}
#endif /* _PRIMARY_HEADER_H */
定义它的我的主要函数的实现文件。
/* primary_impl.c */
#include "primary_header.h"
#include <stdio.h>
/* Define the primary workhorse function */
void primary()
{
/* do the main work */
printf("I'm the primary function, I'm doin' work.\n");
/* also get some help from the helper function */
helper();
}
一个 main()
文件,通过调用 primary()
来测试代码
/* main.c */
#include "primary_header.h"
int main()
{
/* just call the primary function */
primary();
}
问题
正在使用
gcc main.c primary_impl.c
不会 link 因为 primary_header.h
文件被包含两次,因此存在函数 helper()
的非法双重定义。为该项目构建源代码以防止双重定义的正确方法是什么?
你几乎从不在头文件中编写函数,除非它被标记为始终内联。相反,您在 .c
文件中编写函数并将函数的声明(而非定义)复制到头文件中,以便它可以在其他地方使用。
你应该只在头文件中写你的函数原型,你的函数体应该写在.c文件中。
这样做:
primary_header.h
/* primary_header.h */
#ifndef PRIMARY_HEADER_H
#define PRIMARY_HEADER_H
#include <stdio.h>
/* Forward declare the primary workhorse function */
void primary(void);
/* Also define a helper function */
void helper(void);
#endif /* PRIMARY_HEADER_H */
primary_impl.c
/* primary_impl.c */
#include "primary_header.h"
#include <stdio.h>
/* Define the primary workhorse function */
void primary()
{
/* do the main work */
printf("I'm the primary function, I'm doin' work.\n");
/* also get some help from the helper function */
helper();
}
void helper()
{
printf("I'm a helper function and I helped!\n");
}
编辑: 将 _PRIMARY_HEADER_H
更改为 PRIMARY_HEADER_H
。正如@Jonathan Leffler 和@Pablo 所说,下划线名称是保留标识符
您可以在头文件中定义一个函数,如果它是 weak linkage,例如:
// test.h
__attribute__((weak)) int test() {
static int s = 0;
return s++;
}
// a.c
#include "test.h"
#include <stdio.h>
void a(){
print("%d", test());
}
// b.c
#include "test.h"
#include <stdio.h>
void b(){
print("%d", test());
}
// main.c
#include "test.h"
#include <stdio.h>
void a();
void b();
void main(){
a();
b();
print("%d", test());
}
cc a.c b.c main.c
不会引发多重定义错误,输出应该是预期的 012
,这意味着 a.c
、b.c
和 main.c
共享相同的 test
功能。
您可以使用 inline
.
在 C++ 中获得相同的结果
此外,弱链接也可以用在变量定义上,允许你在头文件中定义和初始化一个全局变量,而无需源文件(类似于c++中的inline static
)。
注:
Weak symbols are not mentioned by the C or C++ language standards.
所以在c中使用时要小心。但在 c++ 中,inline
和 inline static
是 c++11 和 c++17 的可移植形式。
设置
如果我有这样的程序
一个头文件,它声明了我的主要库函数 primary()
并定义了一个简短的辅助函数 helper()
。
/* primary_header.h */
#ifndef _PRIMARY_HEADER_H
#define _PRIMARY_HEADER_H
#include <stdio.h>
/* Forward declare the primary workhorse function */
void primary();
/* Also define a helper function */
void helper()
{
printf("I'm a helper function and I helped!\n");
}
#endif /* _PRIMARY_HEADER_H */
定义它的我的主要函数的实现文件。
/* primary_impl.c */
#include "primary_header.h"
#include <stdio.h>
/* Define the primary workhorse function */
void primary()
{
/* do the main work */
printf("I'm the primary function, I'm doin' work.\n");
/* also get some help from the helper function */
helper();
}
一个 main()
文件,通过调用 primary()
/* main.c */
#include "primary_header.h"
int main()
{
/* just call the primary function */
primary();
}
问题
正在使用
gcc main.c primary_impl.c
不会 link 因为 primary_header.h
文件被包含两次,因此存在函数 helper()
的非法双重定义。为该项目构建源代码以防止双重定义的正确方法是什么?
你几乎从不在头文件中编写函数,除非它被标记为始终内联。相反,您在 .c
文件中编写函数并将函数的声明(而非定义)复制到头文件中,以便它可以在其他地方使用。
你应该只在头文件中写你的函数原型,你的函数体应该写在.c文件中。
这样做:
primary_header.h
/* primary_header.h */
#ifndef PRIMARY_HEADER_H
#define PRIMARY_HEADER_H
#include <stdio.h>
/* Forward declare the primary workhorse function */
void primary(void);
/* Also define a helper function */
void helper(void);
#endif /* PRIMARY_HEADER_H */
primary_impl.c
/* primary_impl.c */
#include "primary_header.h"
#include <stdio.h>
/* Define the primary workhorse function */
void primary()
{
/* do the main work */
printf("I'm the primary function, I'm doin' work.\n");
/* also get some help from the helper function */
helper();
}
void helper()
{
printf("I'm a helper function and I helped!\n");
}
编辑: 将 _PRIMARY_HEADER_H
更改为 PRIMARY_HEADER_H
。正如@Jonathan Leffler 和@Pablo 所说,下划线名称是保留标识符
您可以在头文件中定义一个函数,如果它是 weak linkage,例如:
// test.h
__attribute__((weak)) int test() {
static int s = 0;
return s++;
}
// a.c
#include "test.h"
#include <stdio.h>
void a(){
print("%d", test());
}
// b.c
#include "test.h"
#include <stdio.h>
void b(){
print("%d", test());
}
// main.c
#include "test.h"
#include <stdio.h>
void a();
void b();
void main(){
a();
b();
print("%d", test());
}
cc a.c b.c main.c
不会引发多重定义错误,输出应该是预期的 012
,这意味着 a.c
、b.c
和 main.c
共享相同的 test
功能。
您可以使用 inline
.
此外,弱链接也可以用在变量定义上,允许你在头文件中定义和初始化一个全局变量,而无需源文件(类似于c++中的inline static
)。
注:
Weak symbols are not mentioned by the C or C++ language standards.
所以在c中使用时要小心。但在 c++ 中,inline
和 inline static
是 c++11 和 c++17 的可移植形式。