从helloworld.c到a.out(2)预处理

本章介绍处理源代码的第一步:预处理

只所以说是处理源代码的第一步,而不是编译的第一步,是因为准确来讲,预处理是发生在编译之前的事情,不属于微观意义上编译的过程。

那么下面就来探讨一下,预处理到底发生了什么。

假设有如文件tmp.c中下一段代码

#include <stdio.h>
#include <stdlib.h>

#define TMP 3

int main()
{
	int tmp = TMP;
	printf("tmp = %d \n", tmp);
	return;
}

然后对这个文件执行gcc -E tmp.c -o tmp.i (gcc的-E选项为只进行预处理操作)

生成的tmp.i即为tmp.c经过预处理之后的的文件,ll看一下,发现这个文件要比c文件大很多

-rw-rw-r--  1 yejing yejing   125 Oct 16 07:17 tmp.c
-rw-rw-r--  1 yejing yejing 41648 Oct 16 07:17 tmp.i

那么到底具体多了什么呢?

截一段出来看看

# 1 "tmp.c"
# 1 "<command-line>" //如果有人知道,烦请指导一下,这一行是什么意思?
# 1 "tmp.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 28 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 324 "/usr/include/features.h" 3 4
# 1 "/usr/include/i386-linux-gnu/bits/predefs.h" 1 3 4
# 325 "/usr/include/features.h" 2 3 4
# 357 "/usr/include/features.h" 3 4
# 1 "/usr/include/i386-linux-gnu/sys/cdefs.h" 1 3 4
# 378 "/usr/include/i386-linux-gnu/sys/cdefs.h" 3 4
# 1 "/usr/include/i386-linux-gnu/bits/wordsize.h" 1 3 4
# 379 "/usr/include/i386-linux-gnu/sys/cdefs.h" 2 3 4
# 358 "/usr/include/features.h" 2 3 4
# 389 "/usr/include/features.h" 3 4
# 1 "/usr/include/i386-linux-gnu/gnu/stubs.h" 1 3 4

gcc官方网站是这么解释这个这个格式的(https://gcc.gnu.org/onlinedocs/gcc-4.3.6/cpp/Preprocessor-Output.html)

# linenum filename flags

These are called linemarkers. They are inserted as needed into the output (but never within a string or character constant). 
They mean that the following line originated in file filename at line linenum. 
filename will never contain any non-printing characters; they are replaced with octal escape sequences. 

//文件名不包含无法打印字符,他们将被八进制转义字符代替

对后面的标志的具体解释如下:
After the file name comes zero or more flags, which are `1', `2', `3', or `4'. If there are multiple flags, spaces separate them. Here is what the flags mean: 

//文件名之后是0到多个标志,有可能是1,2,3,4,如果有多个标志,用空格分隔,下面是各个标志的具体意思
`1'
This indicates the start of a new file. //1表示这是个以新行
`2'
This indicates returning to a file (after having included another file). //2表示要返回一个文件(表include的文件include了另外一个文件)
`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. 

//表示以下代码应该被当做类似被extern“C”包含的代码块来处理


前面的文章说了,宏观意义上的编译实际上包括了预处理,编译,汇编,连接等流程,所以我们常用的的gcc实际上也不是一个程序,而是多个程序组成的package,

其中包括预处理器cpp,编译器ccl(高版本的gcc已经将预处理合到了ccl中),汇编器ar,链接器ld等。


实际上完成上述gcc -E动作的就是cpp,

cpp作为一个单独的应用程序,有些常用的选项参数,比如-I和-D,

-I可以用于处理头文件的包含,-I包含的头文件,可以直接include,而不用使用相对路径

-D可以用于灵活的打开或者关闭用-D之后的宏控制的代码块


上面是举例说明了预处理大概做了些什么,下面介绍下,预处理主要处理源文件中的哪些部分。

总体来说,主要是以“#”开头的行。

1,#define、#undef:宏的定义及却小

2,#include:头文件的包含,

3,#line num:#line所在行的下一行行号为num

#include <stdio.h>

#line 30
int main(){
    printf("%d \n", __LINE__);
    return 1;
}
程序输出32

4,#error text:如果执行到带#error的行,编译会推出,并输出后面的text给用户,make中也有类似的函数

5,#program:(http://blog.csdn.net/welcome_ck/article/details/232434),这个命令比较少用,之前这个blog做了比较详细的介绍。

6,#if、#ifdef、#ifndef、#elif、#else、#endif:代码块编译控制



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值