多次包含标题库时重复符号

时间:2017-12-29 10:02:50

标签: c

我为一个小小的游戏制作了一个简单的帮助库。在这样的库中,我有一些必须尽可能快地执行的核心功能,因为它们在每个游戏帧中被调用了数千次。

如果我宣布他们"内联"并将他们的声明(library.h)从他们的实现(library.c)中拆分并将它们包含在游戏文件(game.c)中,我猜他们自从声明它们后没有内联/优化直接在game.c中使用gcc -O3编译游戏可以让我的性能提升超过60倍。

为了解决这个问题,我决定让我的库成为一个仅限标题的库。我在library.h中拥有所有框架常量,变量和函数。将其包含在game.c中仍然可以获得最佳效果。

现在,问题在于每当我将library.h包含在多个文件中时(例如game1.cgame2.c),我会在编译时得到一长串duplicate symbol错误游戏。该库有#pragma once,但问题仍然存在。

如何实际编写仅限标头的库或确保实际优化外部库中的内联函数?

由于

1 个答案:

答案 0 :(得分:2)

正如已经评论的那样,你需要在头文件static中声明函数和全局变量。

static关键字表示对象(函数或变量)具有内部链接;它只在当前编译单元中可见,并且不会包含在任何符号表中。

使用包含警卫也是一个好主意,这样如果你有另一个包含标题的头文件,并且C源文件包含你的头文件和其他头文件,那么你的头文件只包含一次。 (带有FOOLIB_H的行包含以下示例中的包含保护。)

考虑以下简单的固定大小的堆栈示例 foolib.h

#ifndef   FOOLIB_H
#define   FOOLIB_H

#include <stdlib.h>

#define   STACK_MAX  256

static size_t  stack_size = 0;
static double  stack_item[STACK_MAX];

static inline int  stack_push(const double  item)
{
    if (stack_size < STACK_MAX) {
        stack_item[stack_size++] = item;
        return 0;
    } else
        return -1;
}

static inline double  stack_pop(const double  empty)
{
    if (stack_size > 0)
        return stack_item[--stack_size];
    else
        return empty;
}

#endif /* FOOLIB_H */

包含上述(#include "foolib.h")的每个编译单元(您单独编译的每个源文件)都可以通过stack_push()stack_pop()获取他们自己的本地私有堆栈。

标记函数static inline而不仅仅是static的原因是前者告诉编译器可以完全省略该函数,如果没有使用它。特别是,如果使用gcc -Wall编译代码,gcc会警告是否未使用static函数,但如果未使用static inline函数则不会发出警告。除此之外,没有太大的实际差异。