【问题标题】:How to handle typedef datatypes in C (generally speaking)?如何处理 C 中的 typedef 数据类型(一般来说)?
【发布时间】:2020-10-07 21:29:47
【问题描述】:

基本上,编译器会抱怨未知类型名称“Song_t”,因为数据类型定义是在首次引用之后发生的。

struct Cell { Song_t song;
            struct Cell *pnext;
};

typedef struct Song Song_t;

如果我把 typedef 放在前面,它可以工作。 因此,通常建议将 typedef 放在每个文件的开头吗?

【问题讨论】:

  • 编译器怎么知道结构定义中的Somg_t是什么?!
  • 阅读Modern C 并查看this C reference
  • 在您的下一个问题中提供一些minimal reproducible example。另请阅读您的 C 编译器的文档(例如 GCC,并在 github.com 等上研究 现有 C 软件的源代码以获取灵感...
  • @BasileStarynkevitch:这不是一个调试问题,不需要最小的可重现示例。问题已经充分提出。
  • @VladfromMoscow:编译器可以检查整个源文件,如果可能,根据文件的完整信息解析类型。这不是因为 C 在很大程度上被设计为一次性编译。但这是学生可能还不知道的关键信息,所以你提出的反问是一个不充分的答案。

标签: c typedef


【解决方案1】:

您不能在定义之前引用 typedef 名称。

要么将 typedef 移到 struct Cell 定义之前,要么在 struct Cell 定义中使用 struct Song

【讨论】:

    【解决方案2】:

    因此通常建议将 typedef 放在每个文件的开头吗?

    不一定,你可以通过编码避免typedef -s

    struct Cell { 
        struct Song song;
        struct Cell *pnext;
    };
    

    当然,struct Song 应该定义在“之前”(考虑到C preprocessor)。

    你也可以编码

    typedef struct Song Song_t;
    typedef struct Cell Cell_t;
    

    并且稍后仅使用Song_t 等。您必须(稍后)提供struct Song 的定义(不仅仅是前向声明)。 详情请阅读Modern C,见this C reference网站,以及C11标准n1570

    Linux kernel 或简单的 C 编译器(如nwcc)或GTK toolkit 的源代码中寻找灵感。所有这些(大部分)都是用 C 编码的。还可以在 github 上查找示例。还要研究GCC的源代码。它是一个流行的 C 编译器(它的旧版本 - 例如 GCC 4.4- 主要是用 C 编码的)。

    【讨论】:

      【解决方案3】:

      C 编译器从上到下一次性解析预处理代码。

      这意味着任何对象或类型在使用之前都必须先定义。

      【讨论】:

      • 完全正确,因为C preprocessor。阅读 C11 标准n1570
      • @BasileStarynkevitch 处理器通常将标记直接输入解析器。因此,它不需要单独的阶段。
      • @PSKocik:这取决于你所说的阶段。在GCC 中甚至没有出现这个词(而且 GCC 是一个 C 编译器)。见documentation of GCC internals。 AFAIK,GCC 有数百个优化通道。查看其文件gcc-10.*/gcc/passes.def
      • C 翻译当然需要对先前扫描的代码进行逆行更改,但其中大部分由链接器处理。例如,在 extern int x; int foo(void) { return x; } int x = 3; 中,foo 的指令无法完全解析,而 foo 正在被扫描且 int x 尚未被扫描。但即使不考虑符号解析,C 的某些方面也需要一些前瞻或逆行工作。例如,switch 语句没有正确编译,至少编译不好,没有关于 case 标签的信息。
      • 当然,优化器会将所有订单抛到窗外。典型的编译器构建流程图和其他描述程序的数据结构,然后对它们执行与源代码顺序无关的各种转换。不能说具有这种处理能力的编译器只从上到下一次通过。
      猜你喜欢
      • 2016-04-23
      • 2022-10-14
      • 1970-01-01
      • 1970-01-01
      • 2010-12-10
      • 2020-11-06
      • 1970-01-01
      • 1970-01-01
      • 2014-08-03
      相关资源
      最近更新 更多