在使用C++很长一段时间后,我不得不返回(嵌入式)C,并出现以下问题:
我有一个源模块,它被包含了很多次,让我们称之为utilities.h
和utilities.c
在里面,我有一个重要的数组,我们称之为
#define IMPORTANT_ARRAY_LENGTH 10000
char important_array[IMPORTANT_ARRAY_LENGTH];
我在这个utilities
模块中还有很多其他功能,它们都可以很好地工作。然而,在另一个源文件中,让我们称之为worker.c
,我必须使用这个数组。在不必将extern char important_array[IMPORTANT_ARRAY_LENGTH]
和宏定义放在worker.c
中的情况下,实现这一点的"官方"优雅方式是什么?
如果我执行以下操作:
公用事业.h
#ifndef _UTILITIES_H_
#define _UTILITIES_H_
#define IMPORTANT_ARRAY_LENGTH 10000
extern char important_array[IMPORTANT_ARRAY_LENGTH];
// ...
公用事业.c
#ifndef _UTILITIES_C_
#define _UTILITIES_C_
#include "utilities.h"
char important_array[IMPORTANT_ARRAY_LENGTH];
// ...
worker.c
#include "utilities.h"
// ...
important_array[0] = 0;
那么我的数组将是CCD_ 7中未定义的符号。如果我在utilities.h
中没有使用extern
关键字,那么它当然是一个重复的符号。(奇怪的是,它只编译了一个警告,我可以从链接器文件中看到大小被分配了多次。)
我真的必须在worker.c
中声明我的数组吗?我想保持一切干净,并且只将所有声明放在一个地方:在头文件中。我只想有一次宏定义(这是次要的,因为我可以使用const,但我希望预处理器处理它,而不是占据位置)
您有一种规范的方法:在头文件中有一个extern
声明,并在.c
文件中定义变量。
我的数组将是worker.c 中未定义的符号
不,不会的。您的代码编译和链接都很好。
我经常把定义放在标题中(我知道这是不受欢迎的)。它将定义和声明紧密结合在一起,这是一件好事。
/* file.c */
#define FILE_C 1
#include "file.h"
/* file.h */
#ifndef FILE_H
#define FILE_H 1
#define BIG_SIZE 13
#if FILE_C
char the_array[BIG_SIZE];
#else
extern char the_array[BIG_SIZE];
#endif
#endif /* FlLE_H */
/* other_file.c */
#include "file.h"
没有做错的风险:如果你做错了,链接器会抱怨。
顺便说一句,一种基本上相同的方法,但可能更可读,是:
/* file.h */
#ifndef FILE_H
#define FILE_H 1
#if FILE_C
#define EXTERN /**/
#else
#define EXTERN extern
#endif
#define BIG_SIZE 13
EXTERN char the_array[BIG_SIZE];
...
#undef EXTERN
#endif /* FlLE_H */
在每个翻译单元中有一个声明(extern...
)和一个定义是实现这一点的最优雅的方法。
因此,将extern char important_array
保留在标头中,并将char important_array
保留在其中一个.c
文件中。
在utility.c中创建一个新函数,名为"get_import_array",它只返回一个指向数组的指针,并将原型放在utility.h中。之后,当您将utility.h放在worker.c中时,您将可以以一种简单而有组织的方式访问important_array。