嵌入式:C语言预处理文件行标记规则

在 GCC 预处理器的输出(.i.ii文件)中,行标记(line marker)的通用格式为:

# linenum filename [flags]

其中 linenum是源代码中的行号,filename是源文件路径,后面的 flags​ 是一个或多个用空格分隔的数字,每个数字代表一种属性。这些数字的含义如下:

数字含义说明
1开始一个新文件(Start of new file)表示从此处起进入一个新的包含文件(#include引入的文件)。
2返回到上一个文件(Return to previous file)表示从包含文件返回,继续处理上一级文件。
3此文件来自系统头文件(System header)标记该文件是系统头文件(如 /usr/include/下的文件),编译器会对其中的警告进行抑制。
4视为 C++ 的 extern "C"块(Extern "C" block)表示该文件的内容应被当作 extern "C"包裹,用于 C/C++ 混合编译时避免名字修饰。

The C Preprocessor中,对行标记的解释如下:

1​: This indicates the start of a new file.
2: This indicates returning to a file (after having included another file).  
3: This indicates that the following text comes from a system header file, so certain warnings should be suppressed.  
4: This indicates that the following text should be treated as being wrapped in an implicit `extern "C"`block.

如下面代码中:

# 1 "kernel/FreeRTOS-orig/Source/include/FreeRTOS.h" 1
# 33 "kernel/FreeRTOS-orig/Source/include/FreeRTOS.h"
# 1 "/rtos/lichee/rtos/tools/riscv64-elf-x86_64-20201104/lib/gcc/riscv64-unknown-elf/8.4.0/include/stddef.h" 1 3 4
# 149 "rtos/lichee/rtos/tools/riscv64-elf-x86_64-20201104/lib/gcc/riscv64-unknown-elf/8.4.0/include/stddef.h" 3 4 

这些标志可以组合出现,GCC 会在行标记后依次列出所有适用的标志。例如:

  • # 1 "FreeRTOS.h" 1
    表示进入 FreeRTOS.h 文件,且是新文件的开始(flag=1)。
  • # 33 "FreeRTOS.h"
    没有 flag,表示仍在 FreeRTOS.h 中,第 33 行,无特殊属性。
  • # 1 "stddef.h" 1 3 4
    进入 stddef.h,且它既是新文件(1)、又是系统头文件(3)、还相当于 extern "C"块(4)。
  • # 149 "stddef.h" 3 4
    仍在 stddef.h 中,第 149 行,此时不再是新文件开始(没有 1),但仍保留系统头(3)和 extern "C"(4)属性。

示例说明1

  • 标志 2​ 通常出现在文件包含结束处,例如 # 123 "main.c" 2表示从包含文件返回 main.c 的第 123 行。
  • 如果没有任何标志,则默认该行是普通源代码行。
  • 这些行标记主要用于帮助调试器(如 GDB)定位源码位置,同时也影响编译器的诊断行为(如对系统头文件少报 warning)。

在以上例子中,# 1 "stddef.h" 1 3 4意味着:这是一个新包含的系统头文件,并且其内容应当被当作 extern "C"来处理;而后续的 # 149 "stddef.h" 3 4则表示在同一文件中继续,但不再是文件开头(去掉 flag 1)。

示例说明2

以下面代码为例,进行逐行的补充说明

# 10 "drivers/rtos-hal/include/osal/hal_osal.h" 2
# 1 "drivers/rtos-hal/include/osal/hal_status.h" 1
# 4 "drivers/rtos-hal/include/osal/hal_status.h"
# 12 "drivers/rtos-hal/include/osal/hal_osal.h" 2
# 1 "drivers/rtos-hal/include/osal/hal_atomic.h" 1
# 10 "drivers/rtos-hal/include/osal/hal_osal.h" 2
  • 含义:返回到文件 hal_osal.h的第 10 行。
  • 标志 2​ 表示“返回到上一个文件”,即刚刚结束了一个被包含文件的处理,现在继续处理 hal_osal.h中第 10 行及之后的代码。
  • 这一行通常出现在某个 #include指令对应的被包含文件全部展开之后。此处应是前一个包含(例如系统头文件)处理完毕后的返回点。
(空行)
  • 预处理输出中保留的空行,对应原始源文件中的空行或无关紧要的空白。
# 1 "drivers/rtos-hal/include/osal/hal_status.h" 1
  • 含义:开始处理一个新文件 hal_status.h,行号为 1。
  • 标志 1​ 表示“新文件开始”,即遇到 #include "hal_status.h"指令后,预处理器切换到此文件。
  • 这表明 hal_osal.h中包含了对 hal_status.h的引用,且该引用位于 hal_osal.h的第 9 行(因为返回后是第 10 行)。
# 4 "drivers/rtos-hal/include/osal/hal_status.h"
  • 含义:仍在 hal_status.h文件中,当前处理到第 4 行。
  • 此行没有标志(或标志为 0),表示普通源代码行,无特殊属性。
# 12 "drivers/rtos-hal/include/osal/hal_osal.h" 2
  • 含义:从 hal_status.h返回 hal_osal.h的第 12 行。
  • 标志 2​ 再次表示返回上一级文件。
  • 注意返回的行号是 12,而非 10,说明在 hal_osal.h中,#include "hal_status.h"指令位于第 9 行,返回后是第 10 行;随后第 10~11 行可能包含其他代码(如空行、注释或其他预处理指令),然后第 12 行是下一个 #include指令的位置。
# 1 "drivers/rtos-hal/include/osal/hal_atomic.h" 1
  • 含义:开始处理新文件 hal_atomic.h,行号为 1。
  • 标志 1​ 表示新文件开始,即 hal_osal.h在第 12 行通过 #include "hal_atomic.h"引入了此文件。
包含顺序
  1. hal_osal.h首先被 hal_atomic.c包含(之前行标记可见)。
  2. hal_osal.h在处理过程中,先包含系统头文件(未在此片段中完全展示),然后返回至第 10 行。
  3. 接着包含 hal_status.h(第 9 行的 #include),处理完后返回 hal_osal.h第 12 行。
  4. 最后包含 hal_atomic.h(第 12 行的 #include),开始处理该文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值