如何在头文件中定义函数?

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.cb.cmain.c 共享相同的 test 功能。 您可以使用 inline.

在 C++ 中获得相同的结果

此外,弱链接也可以用在变量定义上,允许你在头文件中定义和初始化一个全局变量,而无需源文件(类似于c++中的inline static)。

注:

Weak symbols are not mentioned by the C or C++ language standards.

所以在c中使用时要小心。但在 c++ 中,inlineinline static 是 c++11 和 c++17 的可移植形式。