4

设置

如果我有这样的程序

一个头文件,它声明了我的主库函数,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()。什么是构造这个项目的源代码的正确方法,这样就不会发生双重定义?

4

3 回答 3

8

你应该只在头文件中写你的函数原型,你的函数体应该写在一个 .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_HPRIMARY_HEADER_H. 正如@Jonathan Leffler 和@Pablo 所说,下划线名称是保留标识符

于 2018-03-04T20:25:46.160 回答
8

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

于 2018-03-04T20:22:01.463 回答
0

如果它是弱链接,您可以在头文件中定义一个函数,例如:

// 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.c并且main.c共享相同的test功能。您可以在 c++ 中使用inline.

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

笔记:

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

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

于 2021-04-26T20:40:52.793 回答