首页 > 编程语言 > 详细

C语言预处理命令--宏定义

时间:2020-11-02 23:20:03      阅读:32      评论:0      收藏:0      [点我收藏+]

一、宏讲解

1、宏定义

       宏(Macro),是一种批量处理的称谓。计算机科学里的宏是一种抽象(Abstraction),它根据一系列预定义的规则替换一定的文本模式。解释器编译器在遇到宏时会自动进行这一模式替换。

2、C语言宏定义的常规用法

1) 定义符号常量

#define PI 3.1415926

#define MAX_N 10000

2) 定义傻瓜表达式(注意,定义的这种表达式一不小心很容易出现bug,下文会讲)

#define S(a, b) a * b

#define MAX(a, b) (a) > (b) ? (a) : (b)

3) 定义代码段

#define P(a) {\
  printf("%d\n", a);} 

ps:编译器对于宏的解析是很严谨的,只能支持一行解析,\是起连接作用,表示当行的宏代码与下一行宏连接在一起,使得编译器当成一行看待。

3、编译器预定义的宏

在C语言中,我们有很多预定义的宏,就是C语言帮程序员预先定义好的宏,可以让我们使用。

宏                                       说明

__DATE__                            日期:Mmm dd yyyy

__TIME__                             时间:hh:mm:ss

__LINE__                              当前源文件的代码行号

__FILE__                               文件名

__func__                              函数名/非标准

__FUNC__                            函数名/非标准

__PRETTY_FUNCTION__      更详细的函数信息/非标准

4、预定义命令-条件式编译

函数                                     说明

#ifdef DEBUG                      是否定义了DEBUG宏

#ifndef DEBUG                    是否没有定义DEBUG宏

#if MAX_N == 5                  宏MAX_N是否等于5

#elif MAX_N == 4               否则宏MAX_N是否等于4

#else

#endif  

5、预定义命令

技术分享图片

从上图可以看到:

  预编译

  将.c 文件转化成 .i文件

  使用的gcc命令是:gcc –E

  对应于预处理命令cpp

  编译

  将.c/.h文件转换成.s文件

  使用的gcc命令是:gcc –S

  对应于编译命令 cc –S

  汇编

  将.s 文件转化成 .o文件

  使用的gcc 命令是:gcc –c

  对应于汇编命令是 as

  链接

  将.o文件转化成可执行程序

  使用的gcc 命令是: gcc

  对应于链接命令是 ld

  总结起来编译过程就上面的四个过程:预编译、编译、汇编、链接。这里我们主要讲预编译阶段,不去细究其他阶段,具体细节可以去看编译原理的书本。

       预编译是做些代码文本的替换工作。
  处理以# 开头的指令 , 比如拷贝 #include 包含的文件代码,#define 宏定义的替换 , 条件编译等,就是为编译做的预备工作的阶段。
  主要处理#开始的预编译指令,预编译指令指示了在程序正式编译前就由编译器进行的操作,可以放在程序中的任何位置。
C 编译系统在对程序进行通常的编译之前,首先进行预处理。
  C 提供的预处理功能主要有以下三种:
1 )宏定义。
2 )文件包含。
3 )条件编译。

  而我们这里只讲预定义,也就是说,我们可以通过预编译生成的编译源码去看我们的宏替换后有没有符合我们的预期,下面会实际操作。

二、宏使用

  上文,我们知道了宏的三种用法,分别如下:

1) 定义符号常量

2) 定义傻瓜表达式

3) 定义代码段

例子一:

定义一个宏,表示一年有多少秒?

//seconds.c
#include <stdio.h>
#define SEC_OF_A_YEAR (365 * 24 * 60 * 60)

int main(void) {
    printf("%d\n", SEC_OF_A_YEAR);
    return 0;
}

我们对源码进行预编译操作,顺便去查看预编译后的结果,如下

ydq@ubuntu:macro$ gcc -E seconds.c  > seconds.txt
ydq@ubuntu:macro$ tail seconds.txt

# 2 "seconds.c" 2



# 4 "seconds.c"
int main(void) {
    printf("%d\n", (365 * 24 * 60 * 60));
    return 0;
}
ydq@ubuntu:macro$ 

可以看到预编译后,我们的宏SEC_OF_YEAR被替换成了(365 * 24 * 60 * 60),所以我们可以得知,宏定义在预编译后只是进行了简单的代码替换,这其实对于新手来说,是很危险的。

例子二:

请事先一个没有bug的MAX(a, b)宏,需要通过如下测试:

1、MAX(2, 3)

2、5 + MAX(2, 3);

3、MAX(2, MAX(3, 4))

4、MAX(2, 3 > 4 ? 3 : 4)

5、MAX(a++, 6)a的初值为7,函数返回值为7,a的值编程8。

验证1:

1 //max_version1.c 
2 #include <stdio.h>
3 #define MAX(a, b) a > b ? a : b
4 
5 int main(void) {
6     printf("MAX(%d, %d) = %d\n", 2, 3, MAX(2, 3));
7     return 0;
8 }
ydq@ubuntu:macro$ gcc max_version1.c
ydq@ubuntu:macro$ ./a.out 
MAX(2, 3) = 3

由结果得出验证通过,那么我们接着下来在该代码基础上,继续验证2.

1 //max_version2.c
2 #include <stdio.h>
3 #define MAX(a, b) a > b ? a : b
4 
5 int main(void) {
6     printf("MAX(%d, %d) = %d\n", 2, 3, MAX(2, 3));
7     printf("%d + MAX(%d, %d) = %d\n", 5, 2, 3, 5 + MAX(2, 3));
8     return 0;
9 }
ydq@ubuntu:macro$ gcc max_version2.c 
ydq@ubuntu:macro$ ./a.out 
MAX(2, 3) = 3
5 + MAX(2, 3) = 2

  

 

C语言预处理命令--宏定义

原文:https://www.cnblogs.com/ydqblogs/p/13916906.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!