6.1.预处理都做了什么

由我们写好的源代码到CPU可以认识并执行的二进制中间发生了很多事,我们来深入探讨一下C语言的预处理。

1.从源代码到可执行程序的过程
(1)源代码.c文件先经过预处理器,生成一个中间文件.i文件
(2).i文件经过编译生成汇编.s文件
(3).s的汇编文件经过汇编器生成.o的目标文件
(4).o的目标文件经过链接器生成.elf可执行程序

每一步都有其相应的工具,预处理有预处理器,编译有编译器,链接有链接器,这些工具合在一起叫做编译工具链。在windos上的编译器,这些都被所谓的编译器屏蔽了。只留出一个编译的功能,其实叫编译器是不准确的。在Linux中,gcc就是一个编译工具链。gcc包含预处理器,编译器,汇编器,链接器等。

2.gcc中只预处理不编译的方法

gcc xx.c -o 由源码到可执行程序
gcc xx.c -c -o 只编译不连接,生产.o的目标文件
gcc -E xx.c -o xx.i 只预处理产生的中间文件

看只预处理的中间文件有利于我们调试和研究其预处理过程,还记得我们之前说过的#define和typedef的细节差异吗?现在我们就来分析一下,并且看看预处理是个什么过程。

#include<stdio.h>

#define pchar char*
void main(void)
{
    pchar p1,p2;
}

//进行预处理操作,gcc -E xx.c -o xx.i 产生中间文件

#include<stdio.h>


void main(void)
{
    char* p1,p2;
}

分析:
(1)经过预处理后,原来的#define 代码不见了,直接在其所在位置进行替换
(2)#define的替换是简单的替换,就是把所有的pchar 用char*替换
(3)我们看p1,p2的类型。p1shi char*类型的,而p2只是char类型的

再来看typedef的使用

#include<stdio.h>

typedef char* pchar
void main(void)
{
    pchar p1,p2;
}

//预处理后

typedef char * pchar;

void main(void )
{

 pchar p1,p2;

}

我们发现没有变化。也就是说typedef重定义的类型在预处理阶段是不产生变化的,而是在编译阶段发挥作用的。在编译阶段就把pchar当作普通的char*使用。

3.头文件在预处理阶段发生什么变化?
(1)有两种包含方式 第一种:#include<> 第二种:#include””
第一种是用来包含系统提供的头文件的
第二种是用来包含程序员自己写的头文件的

(2)两种包含的区别
第一种:#include< > 的方式,C语言编译器只会到系统指定的目录(编译器配置的目录)去寻找这个头文件,如果找不到就出错。但是编译器允许使用 - i命令添加更多的目录到该系统目录。(不会到当前目录去找)

第二种方式:#include”“的方式,编译器先当前目录下去寻找,如果没有找到则到系统指定的目录去找。这种方式也可以包含系统文件。

总结:(1)虽然可以使用“”来包含系统头文件,但是一般来说,遵从一定的规则。系统文件用<>,自己写的用“”,如果自己写的一大群头文件,也使用<>,把该目录添加到编译器指定的目录去即可。
(2)(头文件包含的实质)在1.c中包含1.h,就是把1.h中的代码原封不动的写到1.c中#include<>语句的原地方去。

—-1.c文件—-

# nclude"1.h"
main()
{
    c = a + b;
    printf("c = %d\n",c);
}
----1.h文件----

int a = 1;
int b = 2;
int c = 0;  

预处理的命令:gcc -E 1.c -o 1.i

结果

# 1 "1.c"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "1.c"
# 1 "1.h" 1
int a = 1;
int b = 2;
int c = 0;
# 2 "baohan.c" 2
main()
{
 c = a + b;
 printf("c = %d\n",c);
}

分析:
(1)前面多了很多我们不认识的东西,不用管它,那是给编译器看的。
(2)在1.c 的#include”1.h”这句代码处,把1.h中的代码全部拷贝到了这里。
(3)需要注意的是,我们写的代码进过预处理后产生了一个.i文件,所有的改动都是在.i文件中。原来的.c文件补货被改动的。

4.注释在预处理阶段的变化

两种条件编译#iddef 和#if( )

#include<stdio.h>
//声明函数
void test(void);
void main()
{
    //定义变量
    int a = 1;
    int b = 2;
}

经过预处理后

#include<stdio.h>

void test(void);
void main()
{

    int a = 1;
    int b = 2;
}

我们发现所有的注释都被删除了。

总结:
(1)注释是给人看的,编译器不用看。
(2)在预处理阶段,预处理器会全部删掉注释。也就是说在编译的时候,编译器根本不知道什么是注释。
(3)预处理器改的是预处理后的一个中间文件.i,而不是源代码.c

5.条件编译在预处理阶段发生了什么?

#include<stdio.h>

#define test 3 //宏定义 test 为3 

void main(void)
{

        #ifdef test 3   //判断 test是不是被宏定义为3,是
        printf(" test 3  !\n");

        #else           //不是

        printf("else !\n");

        #endif

}

预处理后
预处理后被包含进来的stdio.h没有写出来,太长了。

void main(void)
{


 printf(" test 3  !\n");

}

分析:在预处理阶段,条件编译,会判断哪个条件成立,把条件成立的那个语句留下,不成的条件的那个被舍去。(在.i文件中,不是.c文件)

再来看第二种条件编译 #if()

#include<stdio.h>

#define ok 1

main()
{
        #if(ok)

        printf("ok\n");

        #else

        printf("not ok\n");

        #endif
}

//预处理后:

main()
{


 printf("ok\n");

}

总结:
第一种#ifdef 是判断是否该符号被宏定义,在舍弃条件未成立的那一部分
第二种#if() 和if()一样。括号中是一个逻辑真假值。

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
【福建师范大学精品大数据导论课程列表】 福建师范大学精品大数据导论课程系列 (1.1.1)--大数据导论课程简介》PPT.pdf 福建师范大学精品大数据导论课程系列 (2.1.1)--什么是大数据》PPT.pdf 福建师范大学精品大数据导论课程系列 (2.2.1)--1.2 《大数据的价值和作用》PPT.pdf 福建师范大学精品大数据导论课程系列 (2.3.1)--1.3 《大数据时代的思维变革》PPT.pdf 福建师范大学精品大数据导论课程系列 (3.1.1)--2.1 《大数据相关技术基础(1)》PPT.pdf 福建师范大学精品大数据导论课程系列 (3.2.1)--2.2 《大数据相关技术基础(2)》PPT.pdf 福建师范大学精品大数据导论课程系列 (3.3.1)--2.3 《大数据相关技术基础(3)》PPT.pdf 福建师范大学精品大数据导论课程系列 (4.1.1)--3.1 《大数据来源》课件PPT.pdf 福建师范大学精品大数据导论课程系列 (4.2.1)--3.2 《大数据采集》课件PPT.pdf 福建师范大学精品大数据导论课程系列 (4.3.1)--3.3 《大数据预处理》课件PPT.pdf 福建师范大学精品大数据导论课程系列 (4.4.1)--3.4 《大数据集成》课件PPT.pdf 福建师范大学精品大数据导论课程系列 (5.1.1)--4.1.1 hadoop简介之一.pdf 福建师范大学精品大数据导论课程系列 (5.2.1)--4.1.2 hadoop简介之二.pdf 福建师范大学精品大数据导论课程系列 (5.3.1)--4.2 HDFS的简要介绍.pdf 福建师范大学精品大数据导论课程系列 (5.4.1)--4.3 基于HDFS的数据库之一.pdf 福建师范大学精品大数据导论课程系列 (5.5.1)--4.3 基于HDFS的数据库之二.pdf 福建师范大学精品大数据导论课程系列 (5.6.1)--4.3 基于HDFS的数据库之三.pdf 福建师范大学精品大数据导论课程系列 (5.7.1)--4.4 一种基于Hadoop的数据仓库之一.pdf 福建师范大学精品大数据导论课程系列 (5.8.1)--4.4 一种基于Hadoop的数据仓库之二.pdf 福建师范大学精品大数据导论课程系列 (5.9.1)--4.4 一种基于Hadoop的数据仓库之三.pdf 福建师范大学精品大数据导论课程系列 (6.1.1)--5.1 一种并行编程模型--MapReduce-之一.pdf 福建师范大学精品大数据导论课程系列 (6.2.1)--5.1 一种并行编程模型--MapReduce-之二.pdf 福建师范大学精品大数据导论课程系列 (6.3.1)--5.1 一种并行编程模型--MapReduce-之三.pdf 福建师范大学精品大数据导论课程系列 (6.4.1)--5.1 一种并行编程模型--MapReduce-之四.pdf 福建师范大学精品大数据导论课程系列 (6.5.1)--5.2 ApacheSpark之一.pdf 福建师范大学精品大数据导论课程系列 (6.6.1)--5.2 ApacheSpark之二.pdf 福建师范大学精品大数据导论课程系列 (6.7.1)--5.2 ApacheSpark之三.pdf 福建师范大学精品大数据导论课程系列 (7.1.1)--6.1数据描述性分析》课件PPT.pdf 福建师范大学精品大数据导论课程系列 (7.2.1)--6.2 《回归分析》课件PPT.pdf 福建师范大学精品大数据导论课程系列 (7.3.1)--6.3 《聚类分析》课件PPT.pdf 福建师范大学精品大数据导论课程系列 (7.4.1)--6.4 《分类分析》课件PPT.pdf 福建师范大学精品大数据导论课程系列 (7.5.1)--6.5 《Weka软件简》课件PPT.pdf 福建师范大学精品大数据导论课程系列 (8.1.1)--7.1.1 《数据可视化的概念》PPT.pdf 福建师范大学精品大数据导论课程系列 (8.2.1)--7.1.2 《数据可视化的发展历》PPT.pdf 福建师范大学精品大数据导论课程系列 (8.3.1)--7.1.3 《数据可视化技术》PPT.pdf 福建师范大学精品大数据导论课程系列 (8.4.1)--7.2.1 《数据可视化的技术分类》PPT.pdf 福建师范大学精品大数据导论课程系列 (8.5.1)--7.2.2 《数据可视化具体方法》PPT.pdf 福建师范大学精品大数据导论课程系列 (8.6.1)--7.3.1 《数据可视化工具简介》PPT.pdf 福建师范大学精品大数据导论课程系列 (8.7.1)--7.3.2 《Excel数据可视化方法与应用》.pdf

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值