超详细的C进阶教程!(七)C语言预处理

C语言进阶系列 专栏收录该内容
7 篇文章 28 订阅

作者的码云地址:https://gitee.com/dongtiao-xiewei
后续作者会更新力扣的每日一题系列,原代码会全部上传码云,推荐关注哦,笔芯~

还像更深入地了解c语言?快来订阅作者的c语言进阶专栏!作者承诺本系列不会TJ!预计更新:指针,字符串处理,内存管理,结构体,预处理等等

感谢朋友们的支持,我们这个系列今天终于完结啦!

我们一直以来写的代码,本质其实都是以.c文件为后缀名的文本文件,例如我们随便以记事本形式点来一个.c后缀的文件

在这里插入图片描述
点开我们看到,就是我们熟悉的代码样式

但这就有一个问题,这种文本文件是如何被计算机识别的呢?

其实计算机能够识别的就只有机器语言,也就是一串二进制代码,早期的程序员也是全用机器语言编程,后面为了避免麻烦,简化编程的过程,就产生了较为容易理解汇编语言,而汇编过程就是将汇编语言转化为机器语言

而为了解决平台的可移植性和通用性的问题,又产生了高级语言,例如c语言,basic语言等,而编译过程,可把高级语言转化为汇编语言

所以,现代计算机可分为以下几个层次

在这里插入图片描述
我们的c代码若要生成一个可执行程序(二进制代码)需要进行以下几个步骤

在这里插入图片描述
今天的章节我们重点介绍预处理环节

预处理环节将会进行以下工作

  1. 处理define定义好的标识符,宏等
  2. 去掉注释

我们可以先测试一下去掉注释

int main()
{
	printf("hello world!\n");//you can see me!
	return 0;
}

预处理后的结果:
在这里插入图片描述

注:由于VS编译器查看预处理后的代码比较困难,所以本章节的代码我们使用linux平台测试

本节用到的linux指令:
touch test.c创建一个源文件
vim test.c 编写代码
gcc -E test.c -o test.i 将预处理后的代码保存在test.i中

好,坐稳扶好,我们正式开始喽!

#define

#define定义标识符

通用格式:

#define name stuff

例子:

#define MAX 200
#define str struct

我们用这个定义标识符可以起到定义常量,重命名,同名替换等等

可以在linux上简单测试一下

#define MAX 200
#define reg register

int main()
{
	reg int a=MAX;
	printf("%d\n",a);
	return 0;
}

在这里插入图片描述

而代码也能跑的过去
在这里插入图片描述

我们可以看到,预处理阶段就完成了简单替换

萌新最容易犯的错误:在定义完成后加上’’;’'

#define MAX 200;

虽然这个代码可能在有些情况不会出错,但替换下来就是这个结果

在这里插入图片描述
看起来很奇怪,是吧!

#define定义宏

这是define的一个特殊机制,允许把参数替换在文本中

例子

#define DOUBLE(x) (x+x)

通用格式

#define name(list) stuff

宏的使用

在这里插入图片描述

虽然是宏,但我们可以观察到,本质也是简单替换

在这里插入图片描述

我们同样也可以定义以下的宏

#define SQUARE(x) x*x

但是注意,这个宏存在一个问题,假如我们要算这个表达式的结果

SQUARE(5+1)

我们期望结果当然是6的平方,也就是36

但是我们测试发现结果并不是36

在这里插入图片描述
结果居然是11!

我们可以打开test.i文件查看一下预处理后的代码

在这里插入图片描述

我们可以发现,宏仅仅只是完成了简单替换,并没有考虑优先级的问题

这个其实就是根据替换后的算术优先级来计算结果

1*5=5+5+1=11

当然,为了避免算术优先级的问题,我们可以对代码做一点改进

#define SQUARE(x) ((x)*(x))

这样修改后,宏就会是相对独立的运算结果了

在这里插入图片描述

条件编译

在编译一个程序的时候我们如果要将一条语句(一组语句)编译或者放弃是很方便的。因为我们有条件编译指令。

有以下条件编译指令

#ifdef,#ifndef,#if等等

注意,条件编译的末尾一定要加上#endif!

#ifdef

只有你编译了某个宏,代码才会被执行
比如我们在要调试一个代码的场景

在这里插入图片描述

在这里插入图片描述

这里显示了打印字符,如果我们把它注释掉,就不会显示

ifndef

同样还是上面的代码,但是却与上面功能相反

没有定义,才执行下列的程序

应用场景:头文件防止被重复包含

#ifndef __TEST_H__
#define __TEST_H__
//代码

#endif

#if

与分支语句的if相同,例如

在这里插入图片描述

在这里插入图片描述

C语言是编程语言中的一朵奇葩,虽已垂垂老矣,但却屹立不倒,诞生了数十年,仍然是最流行的编程语言之一。C语言看似简单,却不易吃透,想要运用好,更是需要积淀。本书是一本修炼C程序设计能力的进阶之作,它没有系统地去讲解C语言的语法和编程方法,而是只对C语言中不容易被初学者理解的重点、难点和疑点进行了细致而深入的解读,揭露了C语言中那些鲜为普通开发者所知的秘密,旨在让读者真正掌握C语言,从而编写出更高质量的C程序代码。 全书一共11章:第1章重点阐述了C语言中不易被理解的多个核心概念,很多初学者在理解这些概念时都会存在误区;第2~8章对预处理、选择结构和循环结构的程序设计、数组、指针、数据结构、函数和文件等知识点的核心问题和注意事项进行了讲解;第9章介绍了调试和异常处理的方法及注意事项;第10章对C语言中的若干容易让开发者误解误用的陷阱知识点进行了剖析;第11章则对所有程序员必须掌握的几种算法进行了详细的讲解;附录经验性地总结了如何养成良好的编码习惯,这对所有开发者都尤为重要。 本书主要内容:  堆和栈、全局变量和局部变量、生存期和作用域、内部函数和外部函数、指针变量、指针数组和数组指针、指针函数和函数指针、传址和传值、递归和嵌套、结构体和共用体、枚举、位域等较难理解的核心概念的阐述和对比;  预处理中的疑难知识点,包括文件的包含方式、宏定义及其常见错误解析、条件编译指令和#pragma指令的使用等;  if、switch等选择结构语句的使用注意事项和易错点解析;  for、while、do while等循环结构语句的使用注意事项和易错点解析;  循环结构中break、continue、goto、return、exit的区别;  一维数组、二维数组、多维数组、字符数组、动态数组的定义和引用,以及操作数组时的各种常见错误解析;  不同类型的指针之间的区别,以及指针的一般用法和注意事项;  指针与地址、数组、字符串、函数之间的关系,以及指针与指针之间的关系;  枚举类型的使用及注意事项,结构体变量和共用体变量的初始化方法及引用;  传统链表的实现方法和注意事项,以及对传统链表实现方法的颠覆;  与函数参数、变参函数、函数调用、函数指针相关的一些难理解和容易被理解错的知识点解析;  文件和指针的使用原则、技巧和注意事项;  函数调用和异常处理的注意事项和最佳实践;  与strlen、sizeof、const、volatile、void、void*、#define、typedef、realloc、malloc、calloc等相关的一些陷阱知识点的解析;  时间复杂度、冒泡排序法、选择排序法、快速排序法、归并排序法、顺序排序法、二分查找等常用算法的详细讲解;  良好的编码习惯和编程风格。
©️2021 CSDN 皮肤主题: 黑客帝国 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值