转载--c语言宏定义(1)

作者:独舞风

链接:c语言宏定义(1)

1、为什么要有宏定义?

代码中某个特定数值需要参与运算,而且该数值作用于多个地方,当需要对该数值进行修改时,希望只改动一个地方就能实现该数值的全部更新;即便某个数值只用到一次,当修改时也会面临搜索阅读大量代码、数值含义不明晰的问题;某些“操作块”封装成函数时,调用函数开销(保存上下文环境、参数调用、堆栈分配等)太大影响效率,不封装则需要多次输入相同的“操作块”内容,并且修改麻烦容易出现不一致的问题,这时就需要把“操作块”定义成宏,该方案本质是“空间换时间”。

总之,宏的出现时为了:提供代码可读性、增加代码书写效率和提高系统运行效率。

2、宏的产生背景是什么?

宏的本质就是“无条件替换”,而且宏只对程序的文本起作用,它眼中的世界只有文本(字符),没有逻辑运算。记得学习C时,老师告我们:“每条语句后边都要加分号“;”,但是宏定义不能加“,问原因竟然是:”就是不能,记住就行!“。现在知道原因了:如果加了分号,分号就成为了宏定义的一部分,在进行”宏展开“时直接截断语句,当然会出问题。

确切的说, 程序源代码(*.c文件)是不能被计算机直接执行的,编译器需要对程序代码进行“一系列处理”,转换成计算机能读懂的二进制文件(*.bin)。这涉及到编译原理的知识了(如果有机会,我会就编译原理进行讲解),一系列处理包括:预处理(Preprocessing)、编译(Compilation)、汇编(Assembly)、链接(Linking)。“宏展开”过程就发生在“预处理”阶段,编译器负责用实际数据替换掉宏名,所以经过了“预处理”,函数代码中就已经没有所谓宏的概念了。

下面我将做个试验,进行验证:

(1)在Fedora环境下,键入“vi test_macro.c”输入下面的代码并保存

(2)退出vi环境,键入“gcc -E test_macro.c”执行,效果如下

(3)试验结果分析:

"gcc -E test_macro.c" 命令就是告诉编译器只对代码进行预处理,不再进行后续工作直接输出。可以看到,我们定义的宏PI和R都已经不存在了,而且都被替换成了它们各自的常量值。main函数上面的那些函数声明,是stdio.h文件的展开,预处理阶段不只进行了宏展开,还对包含的头文件进行了展开,这里不再细说。

下一节,我们将结合试验数据,对宏使用过程中的一些注意事项进行分析。

时间: 2025-01-02 17:09:56

转载--c语言宏定义(1)的相关文章

转载--c语言宏定义(2)

作者:独舞风 链接:c语言宏定义(2) 1.如何区分宏定义中的“宏名称”和“宏字符串”?对于带参数的宏又该注意什么? 在宏定义中,“宏名称”和“宏字符串”是通过“空格”来区分的,在宏的扩展中,空格会对扩展的结果造成很大的影响.编译器在处理时宏定义时,首先从“#define”后第一个空格开始读取字符串,直到遇见下一个空格为止,两个空格之间的字符串为“宏名称”,确定好“宏名称”之后,本行的所有其他字符串都为“宏字符串”.图示:#define + N个空格(1 < N) + 宏名称(中间没有空格) +

[转载]c语言宏定义

一. #define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能理解该命令的本质,总是在此处产生一些困惑,在编程时误用该命令,使得程序的运行与预期的目的不一致,或者在读别人写的程序时,把运行结果理解错误,这对 C语言的学习很不利. 1 #define命令剖析 1.1   #define的概念 #define命令是C语言中的一个宏定义命令,它用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为

将C语言宏定义数值转换成字符串!

将C语言宏定义转换成字符串! 摘自:https://blog.csdn.net/happen23/article/details/50602667 2016年01月28日 19:15:47 六个九十度 阅读数:10185 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/happen23/article/details/50602667 适用场景举例 流媒体处理系统中,采样率是个很重要的参数,很多地方都要用,如果用来分配内存,则 #define S

常用的C语言宏定义

常用的C语言宏定义 1,防止一个头文件被重复包含      #ifndef COMDEF_H      #define COMDEF_H          //头文件内容      #endif       2,重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植.       typedef   unsigned char       boolean;      /* Boolean value type. */             typedef   uns

C 语言宏定义

C 语言宏定义1.例子如下: #define PRINT_STR(s) printf("%s",s.c_str()) string str = "abcd"; PRINT_STR(str); 结果如下:abcd2.现在我期望打印出,str=abcd, 容易想到的解决办法是: #define PRINT_STR(s) printf("s" "=" "%s",s.c_str()) 打印出来的结果是 s=abcd

C语言宏定义使用技巧

写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性 等等.下面列举一些成熟软件中常用得宏定义...... 1,防止一个头文件被重复包含 #ifndef COMDEF_H #define COMDEF_H //头文件内容 #endif 2,重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植. typedef  unsigned char      boolean;     /* Boolean value type. */ type

C语言:宏定义

C语言程序运行的顺序:源代码 ->编译预处理  ——> 编译 ->链接 -> 运行 编译预处理指令:在编译前进行解析处理的指令 编译预处理指令 1.宏定义   #define 1.1 不带参数宏定义 1.2 带参数的宏定义 2.条件编译 3.文件包含 #include 编译预处理指令: 1.所有编译预处理指令都是以#开头的 2.所有编译预处理指令都是不需要分号 不带参数宏定义:在预编译的时候所出现宏名标识的地方都会被替换成宏名后面的值 注意点: 1.在注释中的宏名不会替换 2.在字

C语言宏定义和宏定义函数

要写好C语言,漂亮的宏定义是非常重要的.宏定义可以帮助我们防止出错,提高代码的可移植性和可读性等. 在软件开发过程中,经常有一些常用或者通用的功能或者代码段,这些功能既可以写成函数,也可以封装成为宏定义.那么究竟是用函数好,还是宏定义好?这就要求我们对二者进行合理的取舍. 我们来看一个例子,比较两个数或者表达式大小,首先我们把它写成宏定义: #define MAX( a, b) ( (a) > (b) (a) : (b) ) 其次,把它用函数来实现: int max( int a, int b)

C 语言宏定义中使用do...while(0)

最近看到C语言的项目中在宏定义中使用了do...while(0),感到是个知识点,特来总结. 先看这句话:do{...}while(0)在C中是唯一的构造程序,让你定义的宏总是以相同的方式工作,这样不管怎么使用宏(尤其在没有用大括号包围调用宏的语句),宏后面的分号也是相同的效果.这句话的意思是说,在宏定义中使用do...while(0)包含的所有语句是一个代码块,不会受到{}:的影响. 看一个例子: #include <stdio.h> #include <stdlib.h> #d