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

时间:2018-03-04 20:18:01

标签: c one-definition-rule include-guards program-structure

设置

如果我有这样的程序

一个头文件,它声明我的主库函数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

没有链接,因为primary_header.h文件被包含两次,因此函数helper()存在非法的双重定义。构造此项目的源代码的正确方法是什么,以便不会发生双重定义?

3 个答案:

答案 0 :(得分:4)

你应该只在头文件中编写你的函数原型,你的函数体应该用.c文件写。

这样做:

primary_header.c

/* 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所说,下划线名称是保留标识符

答案 1 :(得分:3)

除非标记为始终内联,否则几乎不会在头文件中编写函数。相反,您将函数写入.c文件并将函数的声明(非定义)复制到头文件中,以便在其他地方使用。

答案 2 :(得分:0)

你可以在头文件中定义一个函数,如果它是 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 共享相同的 { {1}} 函数。 您可以在 C++ 中使用 test 获得相同的结果。

此外,还可以在变量定义上使用弱链接,允许您在没有源文件的头文件中定义和初始化全局变量(类似于c++中的inline)。

注意:

<块引用>

C 或 C++ 语言标准未提及弱符号。

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