1.1.C语言基础进阶——预处理命令
因为假期实训的开始,另外也是偶然间想起来自己有个CSDN账户,便想开始试着写写博客,顺带着练习下Markdown语法
本周主要是对于C语言基础进阶,对于巩固基础来说还是很重要的
预处理命令
简单来讲就是以#开头的一行语句
主要进行了以下几种的讲解
宏定义
做简单的替换,并不会做运算
对于这句话的理解很重要,在预编译时候,宏定义会被替换为对应的字符,本身并不会进行运算。
#define N 1
其中第一个参数为宏的标识符(名字),第二个参数为替换内容,可以为空
定义符号常量
#include <stdio.h>
#define PI1 3.1415926
#define PI2 1 + 2.1415926
int main(){
printf("PI:%.7lf, 2*PI:%.7lf\n", PI1, 2 * PI1);
printf("PI:%.7lf, 2*PI:%.7lf", PI2, 2 * PI2);
return 0;
}
程序运行结果如下:
不难看出PI2将会被替换为1 + 2.1415926,即2 * 1 + 2.1415926
定义傻瓜表达式
之所以这种叫法大概是因为一般宏定义中的表达式比较简单叭
这里面同样存在之前所说的问题,在替换中我们可能会产生与本身想法相悖的结果
参照下面的例子:
#define MAX(a, b) a > b? a: b
取两个数中较大的数字,乍一看似乎没有什么问题,但是如果运行以下代码
printf("5 + MAX(2, 3) = %d", 5 + MAX(2, 3));
期望的运行结果是8,但是实际上程序会输出2,原因在于替换后实际上程序变为
printf("5 + MAX(2, 3) = %d", 5 + 2 > 3 ? 2: 3));
因为MAX与外界数字互相之间并不独立,导致错误的产生
那我们如果把它们独立起来是不是就没有错误了呢?参考如下代码:
#define MAX(a, b) (a > b? a: b)
//省略部分代码
printf("5 + MAX(2, 3 > 4 ? 3 : 4) = %d", 5 + MAX(2, 3 > 4 ? 3 : 4));
//省略部分代码
这时候替换之后结果是:
printf("5 + MAX(2, 3 > 4 ? 3 : 4) = %d", 5 + (2 > 3 > 4 ? 3 : 4 ? 2 :3 > 4 ? 3 : 4));
可以自己运行下,实际上最后的结果是7而不是9,原因在于a,b两个数之间不互相独立,导致最终替换之后的结果错误
由此我们进一步改进为
#define MAX(a, b) ((a) > (b)? (a): (b))
但是对如下代码依然存在bug:
int a = 5;
printf("%d\n", MAX(a++, 3));
printf("%d", a);
输出结果为6和7,原因在于在替换中,a++两次出现,加了两次
使用中间量操作,最终得到的无bug的宏定义表达式为:
//__typedef(a)为内置宏,返回所给参数的数据类型
#define MAX(a, b) ({\
__typedef(a) _a = (a), _b = (b);\
_a > _b ? _a : _b;\
})
比开始时候要复杂很多了……
定义代码段
实际上在上面的更改中我们已经使用过类似操作,此处给出一个示例:
#define P(a){ \
printf("%d\n", a);\
}
预定义的宏
列出部分系统中预定义的宏:
名称 | 作用 |
---|---|
__DATE__ | 日期 mm dd yyyy |
__TIME__ | 时间 hh:mm:ss |
__LINE__ | 行号 |
__FILE__ | 文件名 |
__func__ | 函数名/非标准 |
__FUNC__ | 函数名/非标准 |
__PRETTY_FUNCTION__ | 更详细的函数信息/非标准 |
其中除了行号,均为字符串类型,行号为整型
条件式编译
宏语句 | 解释 |
---|---|
#ifdef DEBUG | 是否定义了DEBUG宏 |
#ifndef DEBUG | 是否没定义DEBUG宏 |
#if MAX_N == 5 | 宏MAX_N是否等于5 |
#elif MAX_N == 4 | 否则宏MAX_N是否等于4 |
#else | 类似C中else |
#endif | 条件式编译最后要放上,表示条件结束 |
典型应用,用于避免编译时候对函数的多次声明,可以在头文件中加入如下类似语句
#ifdef _IS_PRINE_H
#define _IS_PRIME_H
//函数和变量的声明语句
#endif