IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C语言补坑系列1】C预处理器 -> 正文阅读

[C++知识库]【C语言补坑系列1】C预处理器


前言

嗯,就是给自己的过去补坑。


一、总述

C预处理器在程序执行之前会查看程序,故称为预处理器。

根据程序中的预处理器质量,预处理器把符号缩写替换成其表示的内容。预处理器中可以包含程序所需的其他文件,可选择让编译器查看哪些代码。

故,预处理器的功能是:把一些文本转换成另一些文本。


二、编译器翻译程序

预处理开始前,编译器会先对预处理器中的代码进行翻译处理。

大致步骤如下:

1. 字符映射

编译器将源代码中的字符映射到源字符集,该过程处理多字节字符和三字符序列。

2. 删除换行实例

编译器定位每个反斜杠后面跟着的换行符实例,并删除它们,将预处理表达式整理出一个逻辑行。

注:
1)此处换行符是指:按下Enter键在源代码文件中换行而产生的字符。
2)一个逻辑行可以是多个物理行。

3. 文本划分

编译器把文本划分成预处理记号序列、空白序列和注释序列。

注:编译器将用一个空格字符替换每一条注释。

4. 准备进入预处理

预处理器查找一行中以#号开始的预处理指令。

ps:
① 预处理器指令从#开始运行,到后面的第1个换行符为止。即,指令的长度仅限于一行。
② 预处理器指令可以出现在源文件的任何地方,其定义从指令出现的地方到该文件末尾有效。


三、明示常量:#define

#define预处理器指令和其他预处理器指令一样,以#号作为一行的开始。

常使用#define指令来定义明示常量(manifest constant)(也叫,符号常量),但是该指令还有许多其他用途。

1. 组成

每行#define(逻辑行)都由3部分组成:
1:#define指令本身;
2:是选定的缩写,也称为宏;
3:指令行的其余部分,称为替换体/替换列表。

编译器替换宏的过程称为:宏展开。
如果替换的字符串中还包含宏,则继续替换这些宏。唯一例外的是双引号中的宏。
在这里插入图片描述
图源:C Prime Plus

关于
① 代表值的宏:类对象宏;带有参数的宏:类函数宏
宏的命名:宏的名称中不允许有空格,只能使用字符、数字和下划线(_)字符,而且首字符不能是数字。

Note:
在这里插入图片描述
图源:C Prime Plus

2. 类函数宏(带参数)

注:
① 预处理器不做计算、不求值,只替换字符序列。
② 避免用++x 作为宏参数。
③ C允许在字符串中包含宏参数。在类函数宏的替换体中,#号作为一个预处理运算符,可以把记号换成字符串。例如,如果x是一个宏形参,那么#x就是转换为字符串"x"的形参名。这个过程称为字符串化。

3. ##运算符

① ##运算符可用于类函数宏的替换部分。
② ##可用于对象宏的替换部分。##运算符把两个记号组合成一个记号。

4. 变参宏

通过把宏参数列表中最后的参数写成省略号(即,3个点…)来实现这一功能。这样,预定义宏_ _VA_ARGS_ _可用在替换部分中,表明省略号代表什么。

记住,省略号只能代替最后的宏参数。


四、文件包含:#include

简述:

当预处理器发现#include 指令时,会查看后面的文件名并把文件的内容包含到当前文件中,即替换源文件中的#include指令。这相当于把被包含文件的全部内容输入到源文件#include指令所在的位置。

两种形式:

#include <stdio.h>		// 文件名在尖括号内,在查找系统目录中查找该文件;
#include "mystuff.h"	// 文件名在双引号中,在当前目录或文件名中指定的其它目录中查找该文件;

注:自己编写头文件时,将函数的声明和指令放在XXX.h头文件中,函数的定义放在XXX.c/cpp源文件中。


五、指令合集

1. #undef指令:用于取消/移除已经定义的#define指令。

注:
① #define宏的作用域从它在文件中的声明处开始,直到用#undef指令取消宏为止,或延伸至文件尾(以二者中先满足的条件作为宏作用域的结束)。
② 如果宏通过头文件引入,那么#define在文件中的位置取决于#include指令的位置。
③ 预定义宏,如__DATE__和__FILE__,这些宏一定是已定义的,而且不能取消定义。

在这里插入图片描述
图源:C Prime Plus

2. 条件编译

#ifdef、#else、#endif指令,用法如条件语句。

#ifndef指令与#ifdef指令的用法类似,也可以和#else、#endif一起使用,但是它们的逻辑相反。#ifndef指令判断后面的标识符是否是未定义的,常用于定义之前未定义的常量。

#ifdef:如果XX宏已定义,则…;
#ifndef:如果XX宏未定义,则…。

#ifndef指令通常用于防止多次包含一个文件。

#if和#elif指令
#if后面跟整型常量表达式,如果表达式为非零,则表达式为真。可以在指令中使用C的关系运算符和逻辑运算符;#elif则是if else中的else,即#if与#elif配对使用(注意与#ifdef和#else的用法区分)。


宏和函数的选择

有些编程任务既可以用带参数的宏完成,也可以用函数完成。
实际上,使用宏比使用普通函数复杂一些,稍有不慎会产生奇怪的副作用。

宏和函数的选择实际上是时间和空间的权衡。
一方面:宏产生内联代码,即在程序中生成语句;函数在程序中只有一份语句副本。在多次调用时,函数比宏节省空间;
另一方面:函数的调用需要从主调程序进入函数内,在返回主函数,这比内联代码花费的时间多。

但,宏有一个优点:
不用担心变量类型,因为宏处理的是字符串,而不是实际的值。


总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-22 14:29:00  更:2021-09-22 14:30:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 22:24:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码