如何解释C预处理器输出中的#前缀行? [英] How to interpret #-prefixed lines in C preprocessor output?

查看:71
本文介绍了如何解释C预处理器输出中的#前缀行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是hello.c的代码:

  #include< stdio.h> 

int
main(void)
{
printf( Hello,world!\n);
返回0;
}

我使用了命令 gcc -E hello.c 对其进行预处理,并得到以下输出:

 #1 hello.c 
#1<内置>
#1<命令行>
#1 /usr/include/stdc-predef.h 1 3 4
#1<命令行> 2
#1 hello.c
#1 /usr/include/stdio.h 1 3 4
#27 /usr/include/stdio.h 3 4
#1 /usr/include/features.h 1 3 4
#375 /usr/include/features.h 3 4
#1 / usr / include / sys / cdefs.h 1 3 4
#392 /usr/include/sys/cdefs.h 3 4
#1 /usr/include/bits/wordsize.h 1 3 4
#393 /usr/include/sys/cdefs.h 2 3 4
#376 /usr/include/features.h 2 3 4
#399 / usr / include / features.h 3 4
#1 /usr/include/gnu/stubs.h 1 3 4
#10 /usr/include/gnu/stubs.h 3 4
#1 /usr/include/gnu/stubs-64.h 1 3 4
#11 /usr/include/gnu/stubs.h 2 3 4
#400 / usr /include/features.h 2 3 4
#28 /usr/include/stdio.h 2 3 4





#1 /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stddef.h 1 3 4
#212 / usr / lib / gcc / x86_64-redhat- linux / 4.8.5 / include / stddef.h 3 4
typedef long unsigned int size_t;
#34 /usr/include/stdio.h 2 3 4

#1 /usr/include/bits/types.h 1 3 4
#27 /usr/include/bits/types.h 3 4
#1 /usr/include/bits/wordsize.h 1 3 4
#28 /usr/include/bits/types.h .h 2 3 4


typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
typedef unsigned long int __u_long;


typedef签名的字符__int8_t;
typedef unsigned char __uint8_t;
typedefsigned short int __int16_t;
typedef unsigned short int __uint16_t;
typedefsigned int __int32_t;
typedef unsigned int __uint32_t;

typedef签署了long int __int64_t;
typedef unsigned long int __uint64_t;
/////以下我省略了很多。

我知道这些信息可用于调试符号。但是我想知道每个FIELD的含义。但是,如果您能够回答以下问题,您的回答也将被接受。


  1. #1是什么?<内置>和#1< command-line> 是什么意思?为什么它给我内置和命令行的信息,而这完全不相关?

  2. #1 /usr/include/stdc-predef.h 1 3 4 是什么意思? 1 3 4是什么意思?

谢谢。请注意,我知道预处理器将包含头文件。我想知道预处理输出的每个FIELD的含义。

解决方案

预处理器输出的字段记录在 9个预处理程序输出 GNU cpp手册的


字段为:

 #linenum文件名[标志] 
...

这样的一行表示紧随其后的 ... )起源于文件文件名中的行
编号 linenum 。可选的标志是:-


'1'


这表示新文件的开始。


'2'


这表示返回文件(包含另一个文件后)。 / p>

'3'


这表明以下文本来自系统头文件,因此应禁止某些警告。


'4'


这表示应将以下文本视为包装在隐式外部 C中。


您会看到嵌套来自 #include 指令,例如

 #1``hello.c''; 
#1 /usr/include/stdio.h 1 3 4
#27 /usr/include/stdio.h; 3 4
#1 /usr/include/features.h; 1 3 4
#375 /usr/include/features.h; 3 4
#1 /usr/include/sys/cdefs.h; 1 3 4
...

告诉我们:



  • hello.c 的第1行开始一个新文件 / usr / include / stdio.h ;

  • 在第27行,开始另一个新文件 / usr / include / features.h

  • 在第375行中启动另一个新文件 / usr / include / sys / cdefs.h

  • ...


这不容易阅读。


特殊的文件名包括: <内置> <命令行> 将始终在上下文中裁剪
类似于:-

 #1 hello.c 
#1<内置>
#1<命令行>
#1 /usr/include/stdc-predef.h; 1 3 4
#1<命令行> 2
#1 hello.c

在任何文件的预处理输出的顶部。详细信息可能会随GCC版本的不同而有所不同。


您可能会猜到,<内置> <命令行> 不是真实文件。它们
是预处理器令牌的非文件源,需要以输出格式以某种方式表示
,因此将视为它们是文件。称它们为伪文件


<内置> 是包含以下内容的伪文件编译器的内置宏
定义。有关查看此伪文件内容的方法,请浏览至
GCC转储预处理器定义


<命令行> 当然是预处理程序(通常为GCC)命令行,
被视为宏定义的来源(甚至可能是未定义的),例如

  gcc ... -DFOO = 1 -UBAR ... 

因此,您的示例:

 #1 hello.c 
#1<内置>
#1<命令行>
#1 /usr/include/stdc-predef.h 1 3 4
#1<命令行> 2
#1 hello.c
#1 /usr/include/stdio.h 1 3 4
...

表示此过程:



  • 开始读取 hello.c ,然后

  • 立即读取内置宏的伪文件,然后

  • 立即读取命令行伪文件,然后

  • 立即读取预定义的宏文件 / usr /include/stdc-predef.h
    ,好像它是 一样,它已由 -include / usr / include /预先包含在命令行中stdc-predef.h ,然后

  • 继续并完成读取命令行伪文件,然后

  • 继续阅读 hello.c ,然后

  • 开始阅读 /usr/include/stdio.h

    ...


The following is the code of hello.c :

#include <stdio.h>

int
main (void)
{
  printf ("Hello, world!\n");
  return 0;
}

I used the command gcc -E hello.c to preprocess it, and got the following output:

# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "hello.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 375 "/usr/include/features.h" 3 4
# 1 "/usr/include/sys/cdefs.h" 1 3 4
# 392 "/usr/include/sys/cdefs.h" 3 4
# 1 "/usr/include/bits/wordsize.h" 1 3 4
# 393 "/usr/include/sys/cdefs.h" 2 3 4
# 376 "/usr/include/features.h" 2 3 4
# 399 "/usr/include/features.h" 3 4
# 1 "/usr/include/gnu/stubs.h" 1 3 4
# 10 "/usr/include/gnu/stubs.h" 3 4
# 1 "/usr/include/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/gnu/stubs.h" 2 3 4
# 400 "/usr/include/features.h" 2 3 4
# 28 "/usr/include/stdio.h" 2 3 4





# 1 "/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stddef.h" 1 3 4
# 212 "/usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stddef.h" 3 4
typedef long unsigned int size_t;
# 34 "/usr/include/stdio.h" 2 3 4

# 1 "/usr/include/bits/types.h" 1 3 4
# 27 "/usr/include/bits/types.h" 3 4
# 1 "/usr/include/bits/wordsize.h" 1 3 4
# 28 "/usr/include/bits/types.h" 2 3 4


typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
typedef unsigned long int __u_long;


typedef signed char __int8_t;
typedef unsigned char __uint8_t;
typedef signed short int __int16_t;
typedef unsigned short int __uint16_t;
typedef signed int __int32_t;
typedef unsigned int __uint32_t;

typedef signed long int __int64_t;
typedef unsigned long int __uint64_t;
////I omitted a lot in the following.

I know these information can be used for debugging symbols. But I want to know the meaning of each FIELD. However, if you are able to answer the following ones, your answer will also be accepted.

  1. What does # 1 "<built-in>" and # 1 "<command-line>"mean? Why it gave me message of built-in and command-line, which are totally not relevant?
  2. What does #1 "/usr/include/stdc-predef.h" 1 3 4 mean? What is the meaning of 1 3 4?

Thanks. Please note that I know preprocessor will include the header files. I want to know the meaning of each FIELD of the preprocessed output.

解决方案

The fields of the preprocessor output are documented in 9 Preprocessor Output of the GNU cpp manual.

The fields are:

# linenum filename [flags]
...

Such a line means that what follows it (...) originated at line number linenum in file filename. The optional flags are:-

‘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.

You see that nesting arises from #include directives, e.g.

# 1 "hello.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 375 "/usr/include/features.h" 3 4
# 1 "/usr/include/sys/cdefs.h" 1 3 4
...

tells us:

  • At line #1 of "hello.c" start a new file "/usr/include/stdio.h",
  • at line #27 of which start another new file "/usr/include/features.h"
  • at line #375 of which start another new file "/usr/include/sys/cdefs.h"
  • ...

It's not easy reading.

The special "filenames" <built-in> and <command-line> will always crop up in a context resembling:-

# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "hello.c"

at the top of the preprocessed output for any file. Details may vary with GCC version.

As you'd guess, <built-in> and <command-line> are not real files. They are non-file sources of preprocessor tokens that need to be represented somehow in the output format, so they are treated as if they were files. Call them pseudo-files.

<built-in> is the pseudo-file that contains the compiler's built-in macro definitions. For the way to see the contents of this pseudo-file, browse to GCC dump preprocessor defines.

<command-line> is of course the preprocessor (usually GCC) commandline, considered as a source of macro definitions (and possibly un-definitions), e.g.

gcc ... -DFOO=1 -UBAR ...

So your example:

# 1 "hello.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "hello.c"
# 1 "/usr/include/stdio.h" 1 3 4
...

represents this process:

  • Start reading hello.c, and then
  • immediately read the built-in macros pseudo-file, and then
  • immediately read the commandline pseudo-file, and then
  • immediately read the pre-defined macros file /usr/include/stdc-predef.h as if it was pre-included on the commandline by -include /usr/include/stdc-predef.h, and then
  • resume and finish reading the commandline pseudo-file, and then
  • resume reading hello.c, and then
  • start reading /usr/include/stdio.h
    ...

这篇关于如何解释C预处理器输出中的#前缀行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆