文章目录

  • 一:C/C++程序程序编译过程
    • (1)预处理
    • (2)编译
    • (3)汇编
    • (4)链接
  • 二:宏定义
    • (1)数值宏常量
    • (2)字符串宏常量
    • (3)使用宏充当注释
    • (4)使用宏充当表达式
  • 三:宏其他
  • 四:条件编译
    • (1)#ifdef和#ifndef
    • (2)#if
    • (3)文件包含

一:C/C++程序程序编译过程

(1)预处理

  • 预处理主要包括宏定义,文件包含,条件编译,去注释
  • 输入gcc -E hello.c -o hello.i,其中选项E作用是让gcc在预处理后停止编译

(2)编译

  • 此阶段,gcc检查代码的规范性,是否具有语法错误
  • 输入gcc -S hello.i -o hello.s,即可将预处理里的结果继续继续编译

(3)汇编

  • 编译阶段无误后,进入汇编,将“.s”文件转化为“.o”二进制文件
  • 输入gcc -c hello.s -o hello.o,即可将编译停止在此阶段


(打开二进制文件使用od命令)

(4)链接

  • 此阶段,将目标文件与系统库进行链接生成可执行文件。
  • 输入gcc hello.o -o hello,则完成编译

选项 描述
-E 进行预处理,不进行编译,汇编和链接
-S 进行编译,不进行汇编和链接
-c 进行汇编,不进行链接
-o 链接
static 采用静态链接
-g 生成调试信息
-shared 使用动态库
-O0 无优化
-O1 默认优化级别
-O3 优化最高
-w 不生成警告信息
-Wall 生成所有警告信息

二:宏定义

(1)数值宏常量

(2)字符串宏常量

(3)使用宏充当注释

先去掉注释,再进行宏替换

(4)使用宏充当表达式

#define SUM(X) (X)+(X)int main()
{printf("%d\n", SUM(10));return 0;
}

需要注意使用宏充当多条语句时有可能出现一些潜在的问题,比如下面这个宏有两条语句,但是在if后面如果直接跟上宏而没有带花括号就会出现问题

#define INT_VAL(a,b) a=0;b=0

如果需要宏替换大块语句,可以使用do-while(0)结构

#define GIVE_VALUE(a,b) do{a=0;b=0;}while(0)int main()
{int x = 10;int y = 20;int flag = 0;scanf("%d", &flag);printf("before:%d,%d\n", x,y);if (flag)GIVE_VALUE(x, y);elsex = 10, y = 20;printf("after:%d,%d\n", x, y);}

三:宏其他

第一: 宏定义在文件的任何位置都可以,只要是在你使用这个宏之前定义就可以

void show()
{#define M 10printf("show:%d\n", M);
}
int main()
{show();printf("main:%d\n", M);return 0;}

第二 可以使用#undef来结束宏的作用

int main()
{#define M 10//从这里开始printf("main:%d\n", M);printf("main:%d\n", M);printf("main:%d\n", M);
#undef M//到这里结束printf("main:%d\n", M);//错误return 0;}

第三:有如下宏定义

#define foo(4+foo)

按照一般理解 + foo)会展开成(4 + (4 + foo)),然后一直展开下去,直至内存耗尽。但是,预处理器采取的策略是只展开一次 。也就是说,foo只会展开成(4 + foo),而展开之后foo的含义就要根据上下文来确定了。

对于以下的交叉引用,宏体也只会展开一次

#define x(4+y)
#define y(2+x)

其中x展开成(4+y)->(4+(2*x)),y展开成(2 * x) -> (2 * (4 + y))。

#include <stdio.h>
#define N 2
#define M N + 1
#define NUM (M + 1) * M / 2
main() { printf("%d\n", NUM); }

宏只是字符串替换,并没有计算能力,所以最后的结果是(2+1+1)*2+1/2

四:条件编译

(1)#ifdef和#ifndef

  • ifdef:判定宏是否被定义,宏为真假没有关系,倾向于要定义
  • ifndef:判定宏是否没有定义,宏为真假没有关系,倾向于不要定义

下面的例子中没有定义PRINT所以代码只会保留#else这一部分,代码在预处理时直接被裁掉

int main()
{#ifdef PRINT//实际未定义printf("hello\n");
#elseprintf("no print\n");
#endifreturn 0;
}


如果PRINT被定义了,然后换成ifndef,效果也是一样的

#define PRINT//宏被定义
int main()
{#ifndef PRINT//如果没有定义printf("hello\n");
#elseprintf("no print\n");
#endifprintf("continue\n");return 0;
}

(2)#if

  • #if:判定是否存在,以及是否为真,倾向于存在且为真

如下宏PRINT,被定义了但是为0,因此会输出#else里面内容

# define PRINT 0//定义了但是为假int main()
{#if PRINTprintf("hello\n");
#else PRINTprintf("other");
#endifreturn 0;
}

#if可以进行多分支控制

#define HELLO 2//注意这里使用的是==,像!=,<,>等可以使用
int main()
{#if HELLO==1printf("hello1\n");
#elif HELLO==2printf("hello2\n");
#elif HELLO==3printf("hello3\n");
#elseprintf("other\n");
#endifreturn 0;
}


如果要判断多个宏,可以这样进行

#define Condition1 1
#define Condition2 0int main()
{#if Condition1 && Condition2printf("all\n");
#elseprintf("other\n");
#endifreturn 0;
}

(3)文件包含

有一个头文件test.h,为了防止其被重复包含,我们通常的做法就是,在该文件内写上这样的语句。现在看来效果很明显,在第一次包含时#define会被立即被定义,第n次包含时由于_TEST_H被定义了,所以就不会执行

#ifndef _TEST_H
#define _TEST_H#endif // !_TEST_H
  • 其实头文件在展开时,本质就是将其内容经过一些处理后拷贝到了目标源文件

【C语言重点难点精讲】C语言预处理相关推荐

  1. 【C语言重点难点精讲】C语言指针

    文章目录 一:指针入门 二:数组入门 (1)数组的内存空间布局 (2)区分&arr[0]和&arr 三:指针和数组的关系 (1)以指针的形式访问和以数组形式访问 (2)为什么C语言要这 ...

  2. 【C语言重点难点精讲】关键字精讲

    必读: C语言关键字是一个非常重要的话题,因为它能在相当的程度上将C语言的核心内容串联起来,起到一种提纲挈领的效果 下面的内容重点提及的是相应关键字特别值得注意的地方,这些地方是我们经常忽略的,而且考 ...

  3. 【C语言重点难点精讲】C语言文件

    文章目录 一:文件相关概念 (1)什么是文件 (2)文件名 (3)文件类型 二:文件指针 三:文件的打开和关闭 四:文件的顺序读写 (1)写 (2)读 五:文件的随机读取 (1)fseek (2)ft ...

  4. 【C语言重点难点精讲】C语言内存管理

    文章目录 一:相关动态内存函数 (1)malloc和free (2)calloc (3)realloc 二:进程地址空间 三:常见内存错误 C语言内存管理其实是一个很糟糕的话题,很烦这个,但是没有办法 ...

  5. 【C语言重点难点精讲】C语言中的重要符号

    文章目录 一:续接符和转义符 (1)续接符 (2)转义字符 二:单引号和双引号 三:逻辑运算符 四:位运算 四:左移右移 五:前置++和后置++ 六:优先级 一:续接符和转义符 (1)续接符 如果一行 ...

  6. r语言 新增一列数字类型_R语言实战之R语言基础语法精讲(一)

    R是用于统计分析.绘图的语言和操作环境.R是属于GNU系统的一个自由.免费.源代码开放的软件,它是一个用于统计计算和统计制图的优秀工具.在学习R数据科学之前,我们首先要对R语言的基础语法有一个良好的了 ...

  7. c语言程序设计冲刺串讲,C语言程序设计冲刺串讲.ppt

    C语言程序设计冲刺串讲.ppt C语言程序设计,冲刺串讲,温馨提示,离考试只有不足4周的时间了,我们的好多学员对自己没有信心,对此我建议大家不要放弃最后的一线希望,奇迹总是出现在最后.为此我们一定要加 ...

  8. R语言实战应用精讲50篇(十六)--如何实现文字云可视化

    前言 本文跟大家分享R语言信息可视化--文字云. R语言可以轻松处理信息可视化,并且很早就有专用的信息可视化包--WordCloud. 以下是我为大家准备的几个精品专栏,喜欢的小伙伴可自行订阅,你的支 ...

  9. R语言实战应用精讲50篇(十八)-R语言实现分词、词频与词云案例解析

    前言 我真的超爱R语言,原因之一就是R有许多已经写好."开箱即用"的程序包可以直接拿来用:要知道,程序包减少了多少工作量.当然,其他语言也有类似的包,但是貌似没那么多.没那么细.这 ...

最新文章

  1. activemq 控制台怎么看生产信息_Jmeter中间件处理-ActiveMQ
  2. 张正友标定法 【计算机视觉学习笔记--双目视觉几何框架系列】
  3. java 常量接口_java接口定义常量研究
  4. 20145209预备作业01
  5. mysql数据库内存分配_MySQL OOM 系列一 Linux内存分配
  6. Bailian3258 兔子产子【递推+打表】
  7. 23种设计模式(三)组件协作之策略模式
  8. python前端和后端_python是用于前端还是后端开发
  9. H.264(MPEG)-4AVC
  10. 【oracle】Linux环境安装Oracle客户端
  11. ubuntu 20.04 | 美化主题、图标、光标、壁纸、登录背景
  12. Linux中使用 if 、for、while等循环来写脚本
  13. 计算机辅助模具设计实训心得6,模具设计实训心得体会3篇
  14. origin图上显示数据标签_Origin中如何将曲线上的数据显示出来?
  15. 分享教程,制作Srt字幕最简单的方法
  16. nginx+rtmp(或http-flv)+ffmpeg搭建流媒体视频直播服务器
  17. Android系统WebView无法安装,Android系统进程无法加载WebView
  18. lisp语言cond和if套用_方案 – if和cond之间的区别?
  19. 安装群晖系统入门图文教程
  20. c语言十全十美游戏规则,十全十美游戏

热门文章

  1. 第十七节:ES6新增的Map和WeakMap 又是什么东西?
  2. 苹果小圆点怎么弄出来_原来苹果手机轻点2下屏幕就能截图,以前还不知道,太方便了...
  3. 从一套表达和通路数据学习常见的绘图展示方式和报错处理
  4. 简单几步,教你在mac电脑上轻松启用悬停文本!
  5. 1.10 编程基础之简单排序 04 奖学金 7分 python
  6. 第2课 贝贝的图形(vhist)-2019-07-11《聪明人的游戏-提高篇》
  7. java锁的级别_Java锁的那些事儿之JDK锁(ReentrantLock)
  8. sql配置管理器服务是空的_PostgreSQL 12 安装和配置
  9. CentOS8 安装图形界面后,怎么转换为命令行界面
  10. jquery复选框组清空选中的值_防火墙基本配置:配置策略组