我发现了一段让我有点感兴趣的代码,有一个头文件仅声明了用 C 语言编写的嵌入式系统代码中使用的结构。
这是找到的代码示例:
#ifdef _structures_h_
extern struct{
uint16_t State_ON;
uint16_t State_OFF;
uint16_t State_HI;
uint16_t Counter;
}Switch;
#endif
#ifndef _structures_h_
#define _structures_h_
struct{
uint16_t State_ON;
uint16_t State_OFF;
uint16_t State_HI;
uint16_t Counter;
}Switch;
#endif
在使用这些结构的源文件中,在其中一些文件中,包含是这样完成的:
#define _structures_h_
#include "structures.h"
其他只是包含头文件,如下所示:
#include "structures.h"
我的疑问是,是否有某种原因在同一个头文件中以两种方式声明结构?
在头文件管理器中将相同的结构声明为 extern 或不在头文件管理器中声明相同的结构的编码是否有任何差异或相关影响?
这是我第一次发现这样的情况,并且我无法找到使用此功能的合理解释。
这个结构基本上可以归结为:
标题.h
#ifdef _structures_h_
extern struct {
int State_ON;
int State_OFF;
} Switch;
#endif
#ifndef _structures_h_
#define _structures_h_
struct {
int State_ON;
int State_OFF;
} Switch;
#endif
文件1.c
#include "header.h"
void Function();
int main(void)
{
Switch.State_ON = 2;
Function();
}
file2.c
#include <stdio.h>
#define _structures_h_
#include "header.h"
void Function()
{
printf("Switch.State_ON = %d\n", Switch.State_ON);
}
这非常丑陋,因为:
#define _structures_h_
通常的做法如下所示:
标题.h
#ifndef _structures_h_
#define _structures_h_
typedef struct {
int State_ON;
int State_OFF;
} SwitchStruct;
extern SwitchStruct Switch; // declare the Switch variable so that anybody
// who includes header.h can use it
#endif
文件1.c
#include "header.h"
SwitchStruct Switch; // the one and only place where the variable
// Switch is defined
void Function();
int main(void)
{
Switch.State_ON = 2;
Function();
}
file2.c
#include <stdio.h>
#include "header.h"
void Function()
{
// we can use Switch because it is declared in header.h
printf("Switch.State_ON = %d\n", Switch.State_ON);
}
两个代码段之间的区别在于,在第一个代码段(具有
extern
关键字的代码段)中,结构体变量是 declared 但不是 defined。也就是说,代码指定 Switch
变量是在其他地方定义的(可能在另一个翻译单元中,或者可能在同一 TU 中较早包含的标头中)。然而,在第二节中,Switch
变量被正式声明并定义;另请注意,在第二个片段中,还定义了
_structures_h_
标记,以便后续包含的标头将使用第一部分,以防止 Switch
变量的多个定义。但我同意你和其他回答者的观点,这样的代码既令人困惑又容易出错:例如,在没有 _structures_h_
的多个翻译单元中使用该标头可能会导致
Switch
变量的多个定义。另外,与其使用 #ifndef ...
块,一个简单的 #else
就足够了,并使事情变得更清晰(恕我直言)。