让我们说我在IAR的C项目,我正在使用这4个文件。我有一个定义头,另一个外部函数头。我还有两个.c文件,一个用于main,一个用于函数,如下所示。
第一个头文件:header1.h
#ifndef __HEADER1_H
#define __HEADER1_H
#include "header2.h"
#include "otherheader.h"
// bunch of 'define' here
typedef uint8_t macAddr[8];
#endif
另一个头文件:header2.h
#ifndef __HEADER2_H
#define __HEADER2_H
//other extern functions here
extern void getMAC(macAddr deviceAddr);
#endif
main.c文件在这里:
#include "header1.h"
void main ()
{
macAddr dev1Address = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
getMAC(dev1Address);
}
function.c文件在这里:
#include "header1.h"
void getMAC(macAddr deviceAddr)
{
uint8_t transmit[8];
for (int i = 0; i<8; i++)
transmit[i] = deviceAddr[i];
}
报告的错误是:
Error[Pe020]: identifier "macAddr" is undefined
我很难理解为什么这不起作用。第一个标头(其中定义了macAddr
)包括第二个标头(声明getMac()
函数),第一个标头包含在main.c和function.c中。据我所知,没有循环包含(如其他问题所示......如果我错了,请纠正我,并告诉我如何)
答案 0 :(得分:1)
问题是header1.h
包含header2.h
,但header2.h
需要macAddr
尚未定义。
经验法则是每个文件应仅包含所需的文件。因此:
header1.h
只有一个typedef
。它应该只包含stdint.h
。header2.h
需要macAddr
才能运作,因此应该包含header1.h
。main.c
使用getMAC,因此应包含header2.h
。 header1.h
已经包含在内,因此无需包含它。function.c
严格只需要header1.h
,但确保函数声明和定义匹配是一种很好的做法,因此它应该包含header2.h
。似乎header1.h
被用作整体标题,用于包含所有内容(很难确定,因为您的示例文件太少)。这是非常糟糕的练习。它可以增加编译时间,并且由于难以跟踪依赖性而使重构变得困难。
理想情况下,每个标题应该只有一个明确定义的责任。它并非总是可行,但它是一个很好的目标。
只要您使用标题保护,循环包含不是一个大问题,除非需要,否则不包括所有地方。有时您可能需要添加额外的前向声明,但这是关于它的。
以下是一些补充说明:
正如user3629249和其他人所说,你真的不应该声明以_
下划线开头的符号。这些保留用于C标准或编译器使用。
我不建议在数组(或指针)上使用typedef
。在某些情况下,数组会在没有告诉您的情况下衰减到指针,因此在使用typedef
时,这对用户是隐藏的,并且可能会导致错误使用。我会把它换成struct:
typedef struct { uint8_t address[8]; } MAC_T;