我目前正在查看高级工程师编写的代码。代码工作正常,但我想弄清楚一个细节。
他使用了很多全局变量,他的代码被分解为许多单独的文件。因此,他使用一种技术来确保在需要访问它们的地方声明全局变量,但只定义一次。
这项技术对我来说是新的,但我在互联网上阅读了一些文章,并了解它是如何运作的。他用
#undef EXTERN
然后将EXTERN条件定义为空字符串或实际extern。有一篇非常好的文章here解释了它的工作原理。还有一个讨论here
令我困惑的是,我在网上看到的所有示例都建议在所有需要它的源文件中以常规方式包含头文件,除了一个。在这个包含标题的特殊情况下,行前面是一个符号的定义,该符号将确保将EXTERN定义为一个空字符串并依此类推(参见上面的链接)。通常,这个特殊情况在主要或单独的源文件中,专用于声明全局变量。
然而,在我看到的代码中,这个特殊情况是源文件中始终与标题相对应。这是最小的例子:
“ peripheral1.h ”:
#undef EXTERN
#ifndef PERIPHERAL_1_CPP
#define EXTERN extern
#else
#define EXTERN
#endif
EXTERN void function1(void);
“ peripheral1.cpp ”:
#define PERIPHERAL_1_CPP
#include "peripheral1.h"
function1()
{
//function code code here
}
他刚做的代码中的其他任何地方
#include "peripheral1.h"
我的问题是 和为什么有效?换句话说,编译器如何知道在何处定义以及在何处声明函数(或变量或类......)?为什么在上面的示例中可以使用以下行:
#define PERIPHERAL_1_CPP
#include "peripheral1.h"
在实际的peripheral.1.cpp中,而不是在main.cpp或其他地方?
或者我错过了一些明显的东西?
答案 0 :(得分:1)
预处理后的所有源文件(“perripheral1.cpp”除外)都包含序列 外部变量声明,如:
extern int a;
extern int b;
extern int c;
仅在peripheral1.cpp
中,在预处理之后,会有一系列声明:
int a;
int b;
int c;
int d;
是相应变量的暂定定义,在正常情况下等同于外部定义:
int a = 0;
int b = 0;
int c = 0;
int d = 0;
最终结果是,变量在任何地方声明,但只定义一次。
PS。要非常清楚......
换句话说,编译器如何知道定义的位置和位置 只是声明函数(或变量,或类......)?
编译器在遇到语法结构时知道在哪里声明,语法结构在标准中定义为具有声明的语义。 只要遇到语法结构,编译器就知道在哪里定义,语法结构在标准中定义为具有定义的语义。
换句话说,编译器没有知道 - 你明确告诉它你想要它做什么。
答案 1 :(得分:1)
啊,这让我回归(约20年左右)。
这是C代码在多个文件中定义全局变量的一种方法:使用宏定义变量一次,确保只定义一次,然后在其他C代码文件中将其外部,以便您可以使用它。现在它在很多情况下都是多余的,但是它仍然在遗留代码中占有一席之地,并且(很可能)仍然可以在许多现代编译器中运行,坚信它是C代码而不是C ++。
通常使用#define PERIPHERAL_1_CPP
这样的内容来确保包含的唯一性,例如#pragma once
在我自己的代码中,我会使用类似的东西:
#ifndef PERIPHERAL_1_CPP
#define PERIPHERAL_1_CPP
// my includes here
// my code here
#endif
这样你就可以在你的代码中尽可能多地#include文件,甚至在每个代码文件中,你将避免多个定义错误。为了公平起见,我通常使用.h文件进行操作,并使用类似的方法:
// for absolutely insane safety/paranoia
#pragma once
// normally sufficient
#ifndef PERIPHERAL_1_H
#define PERIPHERAL_1_H
// my includes here
// my code here
#endif
我从来没有在cpp文件上尝试过,但今晚将会看到是否有任何好处:)
如果您需要更多信息,请给我一个喊叫声:)