Typedef 在其他 header 中声明,包含在必要的文件中,但产生:错误 [Pe020]:标识符“”未定义。为什么?
Typedef is declared in other header, is included in necessary files, however produced: Error[Pe020]: identifier "" is undefined. Why?
假设我在 IAR 中有 C 语言的项目,并且我正在使用这 4 个文件。我有一个 header 用于定义,另一个 header 用于外部函数。我还有两个 .c 文件,一个用于 main,一个用于函数,如下所示。
第一个 header 文件:header1.h
#ifndef __HEADER1_H
#define __HEADER1_H
#include "header2.h"
#include "otherheader.h"
// bunch of 'define' here
typedef uint8_t macAddr[8];
#endif
另一个 header 文件: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
我有点难以理解为什么这不起作用。第一个header(定义macAddr
)包含第二个header(声明getMac()
函数),第一个header包含在main.c 以及 function.c。据我所知,没有循环包含(正如其他问题所建议的那样......如果我错了请纠正我,并告诉我如何)
问题是 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
被用作用于包含所有内容的整体 header(很难确定,因为您的示例文件太少)。这是一种非常糟糕的做法。它会增加编译时间,并使重构变得困难,因为依赖关系很难跟踪。
理想情况下,每个 header 应该只有一个明确定义的职责。这并不总是可能的,但这是一个很好的目标。
循环包含不是一个大问题,只要您使用 header 守卫,除非需要,否则不要在任何地方包含所有内容。有时您可能需要添加额外的前向声明,但仅此而已。
这里有一些补充说明:
正如 user3629249 和其他人指出的那样,您真的不应该声明以 _
下划线开头的符号。这些保留供 C 标准或编译器使用。
我不建议在数组(或指针)上使用 typedef
。在某些情况下,数组会在不告诉您的情况下衰减为指针,因此当使用 typedef
时,这对用户是隐藏的,并且可能会因粗心使用而导致错误。我会把它包装成结构体:
typedef struct { uint8_t address[8]; } MAC_T;
假设我在 IAR 中有 C 语言的项目,并且我正在使用这 4 个文件。我有一个 header 用于定义,另一个 header 用于外部函数。我还有两个 .c 文件,一个用于 main,一个用于函数,如下所示。
第一个 header 文件:header1.h
#ifndef __HEADER1_H
#define __HEADER1_H
#include "header2.h"
#include "otherheader.h"
// bunch of 'define' here
typedef uint8_t macAddr[8];
#endif
另一个 header 文件: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
我有点难以理解为什么这不起作用。第一个header(定义macAddr
)包含第二个header(声明getMac()
函数),第一个header包含在main.c 以及 function.c。据我所知,没有循环包含(正如其他问题所建议的那样......如果我错了请纠正我,并告诉我如何)
问题是 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
被用作用于包含所有内容的整体 header(很难确定,因为您的示例文件太少)。这是一种非常糟糕的做法。它会增加编译时间,并使重构变得困难,因为依赖关系很难跟踪。
理想情况下,每个 header 应该只有一个明确定义的职责。这并不总是可能的,但这是一个很好的目标。
循环包含不是一个大问题,只要您使用 header 守卫,除非需要,否则不要在任何地方包含所有内容。有时您可能需要添加额外的前向声明,但仅此而已。
这里有一些补充说明:
正如 user3629249 和其他人指出的那样,您真的不应该声明以
_
下划线开头的符号。这些保留供 C 标准或编译器使用。我不建议在数组(或指针)上使用
typedef
。在某些情况下,数组会在不告诉您的情况下衰减为指针,因此当使用typedef
时,这对用户是隐藏的,并且可能会因粗心使用而导致错误。我会把它包装成结构体:
typedef struct { uint8_t address[8]; } MAC_T;