前言
嗯,就是给自己的过去补坑。
一、总述
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提供了大量能使我们快速便捷地处理数据的函数和方法。
|