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.hheader1.h已包含,无需包含。
  • function.c 严格来说只需要 header1.h,但确保函数声明和定义匹配是一种很好的做法,因此它应该包含 header2.h

似乎 header1.h 被用作用于包含所有内容的整体 header(很难确定,因为您的示例文件太少)。这是一种非常糟糕的做法。它会增加编译时间,并使重构变得困难,因为依赖关系很难跟踪。

理想情况下,每个 header 应该只有一个明确定义的职责。这并不总是可能的,但这是一个很好的目标。

循环包含不是一个大问题,只要您使用 header 守卫,除非需要,否则不要在任何地方包含所有内容。有时您可能需要添加额外的前向声明,但仅此而已。


这里有一些补充说明:

  • 正如 user3629249 和其他人指出的那样,您真的不应该声明以 _ 下划线开头的符号。这些保留供 C 标准或编译器使用。

  • 我不建议在数组(或指针)上使用 typedef。在某些情况下,数组会在不告诉您的情况下衰减为指针,因此当使用 typedef 时,这对用户是隐藏的,并且可能会因粗心使用而导致错误。我会把它包装成结构体:
    typedef struct { uint8_t address[8]; } MAC_T;