0

我知道如何编写 .h 文件并包含警卫。我想编写一个包含全局变量的新 bar123.h 文件。假设 bar123.c 不存在。

其他头文件,例如 bar.h 将包括 bar123.h,以使全局变量在需要它们的地方可见。

一个问题是,如果 foo.c 包含 foo.h,而 foo.h 又包含 bar.h,而 bar.h 又包含 bar123.h,那么 foo.c 是否总是包含 bar123.h?

另一个问题是,我应该如何修改 Makefile 和 Kbuild 文件?

我正在寻找一个简单的黑客解决方案。

4

4 回答 4

1

The short of it is this. You can't include a global in a header file and then have that header includes elsewhere. You'll get the nasty "re-definition" error. Unless....

This is what I do.

Header file happy.h

extern int happy; // Global variable

Main file

#include "happy.h"

int happy = 12;

Other file.c

#include "happy.h"

int happy = 10;

On question 2: That depends on the compiler. Some will implicitly add it, however, good coding would be one where you include any .h files that you are intending to use a function from.

Note* It is never a good idea to place globals in a header. The intended use of a header is struct definitions and "public" function declarations. Struct / Union etc definitions are only included in headers when it becomes necessary. Example:

typedef struct
{
    int happy;
    char sad;
} my_mood_t;

my_mood_t *what_is_my_mood( int dog_ate_my_lunch );
于 2013-11-21T06:22:00.933 回答
1

全局变量必须存在于某处,并且只存在于一处。这意味着它只需要在一个地方声明。

请记住:H 文件只是告诉编译器某些东西存在于某处。C 文件提供了这些东西的实际定义。

假设您的全局不属于其他任何地方,我们将添加一个globals.c

#include "globals.h"
int g_myGlobal;

应该有对应的globals.h

#ifndef _GLOBALS_H
#define _GLOBALS_H

extern int g_myGlobal;

#endif // _GLOBALS_H

.h没有extern. 如果您这样做,编译器将尝试在包含该标头的每个 C 文件中声明该变量,这将导致链接时出现“多重定义”错误。(我假设这就是你问“foo.c 总是包含 bar123.h?”的原因,并解释了为什么它不重要。)

main.h

#include "globals.h"
int main() {
    g_myGlobal = 42;
}
于 2013-11-21T06:07:34.883 回答
1

回答您的第一个查询 - 是的 foo.c 将始终包含 bar123.h 。

第二个查询,在 Make 文件中,您需要添加的唯一更改是将此 bar123.h 添加到头包含文件的列表中。由于您没有生成任何新的 .o 文件,因此您不需要更改该部分。

希望它能回答您的疑问

于 2013-11-21T06:07:50.677 回答
0

来自OP的评论:

编译正常,但在运行时我仍然收到“未知符号 baz”。('umac: Unknown symbol baz (err 0)' on the openwrt router serial terminal Tera Term如果有帮助的话。)

如果应用程序链接正常,但无法运行并出现该错误,则意味着在构建时链接期间,具有该符号的动态库可用。但是,在运行时,该符号不可用。快速修复:

  • 确定哪个库有符号
  • 确保该库存在于您运行应用程序的位置,并记下它的路径
  • 不只是运行application,使用命令LD_LIBRARY_PATH=/path/to/the/library/directory application(您也可以LD_LIBRARY_PATH使用该值单独导出,但随后将为每个程序设置它,而不仅仅是那个)。

这不是唯一的方法。您还可以将库复制到系统库目录并运行ldconfig以更新系统库缓存。或者你可以使用rpath机制。但在研究这些之前,先从LD_LIBRARY_PATH环境变量开始让事情正常进行。

于 2013-11-21T09:30:54.710 回答