首页 > 其他分享 >深入理解C语言宏定义

深入理解C语言宏定义

时间:2024-03-30 18:59:19浏览次数:36  
标签:return 定义 int C语言 深入 PRINT 替换 define

目录

一、前言

二、宏的相关语法

2.1 #define

2.2 #undef

2.3 #运算符

2.4 ##运算符

三、宏替换的规则

四、宏与函数


一、前言

        我们都知道#define语句可以定义常量,在编译器预处理时会全部将名字替换为常量。与此同时,#define也允许把参数替换到文本中,这就是本文要重点介绍的宏定义。

二、宏的相关语法

2.1 #define

//语法定义
#define name( parament-list ) stuff
//使用举例
#define DOUBLE(x) (x) + (x)
int main()
{
    int a = DOUBLE(2);
    return 0;
}

2.2 #undef

//用于移除已定义的宏
#undef NAME

2.3 #运算符

  1. 功能:#运算符将宏的⼀个参数转换为字符串字⾯量
  2. 引入:字符串中的n没有被替换
    #define PRINT(n,format) printf("the value of n is "format"\n",n)
    
    int main()
    {
    	int a = 8;
    	PRINT(a,"%d");
    	int b = 69;
    	PRINT(b,"%d");
    	float c = 6.6f;
    	PRINT(c,"%f");
    	return 0;
    }

  3. 修改:
    #include <stdio.h>
    
    #define PRINT(n,format) printf("the value of "#n " ""is "format"\n",n)
    
    int main()
    {
    	int a = 8;
    	PRINT(a,"%d");
    	int b = 69;
    	PRINT(b,"%d");
    	float c = 6.6f;
    	PRINT(c,"%f");
    	return 0;
    }

2.4 ##运算符

  1. 功能:##可以把位于它两边的符号合成⼀个符号
  2. 代码示例:
    #define GENERATED_MAX(type) \
    		type type##_max(type x , type y)   \
    		{	\
    			return x>y?x:y;	 \
    		}
    
    //定义函数
    GENERATED_MAX(int);    
    GENERATED_MAX(float);
    
    int main()
    {
    	int a = int_max(3, 5);
    	printf("%d\n", a);
    	float b = float_max(3.5, 6.7);
    	printf("%.2f\n", b);
    	return 0;
    }

三、宏替换的规则

  1. 在调⽤宏时,⾸先对参数进⾏检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换。
  2. 替换⽂本随后被插⼊到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
  3. 最后,再次对结果⽂件进⾏扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上 述处理过程。
  4. 注意:宏仅仅做替换,不会影响运算优先级
    #define SQUARE(x) x*x
    
    int main()
    {
    	int a = 2;
    	printf("%d\n", a + 1 * a + 1);
    	//替换为 2+1*2+1 = 5
    	return 0;
    }

四、宏与函数

为了区分二者约定俗成:把宏名全部大写        函数名全部小写

由上文可见,有的时候宏定义可以充当函数的功能,那么它们二者究竟有哪些区别呢?

函数宏定义
调试方便逐语句调试不方便调试
递归可以递归不可以递归
代码长度
执行速度相对较慢相对较快
参数类型必须是确认的类型不限类型

标签:return,定义,int,C语言,深入,PRINT,替换,define
From: https://blog.csdn.net/paradiso989/article/details/137090484

相关文章

  • 描述C语言中的进程和线程之间的区别
    描述C语言中的进程和线程之间的区别在C语言中,进程和线程是两个非常重要的概念,它们在操作系统中各自扮演着独特的角色。理解它们之间的区别对于编写高效、可维护的并发程序至关重要。下面将详细阐述进程和线程在C语言中的区别。首先,我们来探讨进程的概念。进程是操作系统分配......
  • 漫步者、西圣、万魔开放式耳机怎么样?深入测评谁更值得买!
    今年开放式耳机已经成为了蓝牙耳机市场的新趋势。凭借着舒适的佩戴和创造安全健康听歌环境的特点,它受到了广大用户的热烈欢迎,尤其是我周围热爱运动的朋友几乎都入手了一款开放式耳机。然而,随着开放式耳机的逐渐走红,许多新手现在可能会感到不知如何选择一款适合自己的好用产品。......
  • 8.C语言的一些练习题坑整理
    总结没有顺序之分想起一个算一个逗号表达式https://blog.csdn.net/qq_43539854/article/details/105757536(参考)设f是实型变量,下列表达式中不是逗号表达式的是_________A.f=3.2,1.0B.f>0,f<10C.f=2.0,f>0D.f=(3.2,1.0)逗号表达式即执行第......
  • 文件管理(C语言)
    文章目录文件管理文件文件的打开/关闭fopenfclose文件的顺序读/写fputcfgetcfputsfgetsfwritefreadfprintffscanf文件的随机读写fseekftellrewind文件结束标志的判定feofferror总结读取文件的函数的返回值fgetcfgetsfread补充函数sprintfsscanf文件缓冲区文件......
  • 【记录】使用python图形库自定义位置组件的技术
    目录使用的技术展示一下这个效果结语使用的技术使用自定义位置的技术可以通过place方法来实现。这里是如何使用这种技术的一般步骤:创建一个Label或Button等组件,并设置相关属性(例如文本、图像、背景色等)。使用place方法设置组件的位置,通过指定x和y参数来调整组件在窗口......
  • springBoot AOP 深入原理,及 @Before,@Around,@After,@AfterReturn,@AfterThrowing执行
    连接点(Joinpoint):程序能够应用通知的一个“时机”,这些“时机”就是连接点,例如方法被调用时、异常被抛出时等等。——可以理解为被aop拦截的类或者方法就是连接点。通知(Advice):通知定义了切面是什么以及何时使用。描述了切面要完成的工作和何时需要执行这个工作。——可以理解为被......
  • C语言---自定义类型:结构体
    文章目录前言1.结构体类型的声明2.结构体变量的创建和初始化2.1.创建结构体变量2.2.结构体变量的初始化2.3.嵌套结构体变量2.4.结构体的自引用3.结构成员访问操作符3.1.结构体成员的直接访问3.2.结构体成员的间接访问4.结构体内存对齐4.1对齐规则4.2为什么存在内......
  • 定义类强化——定义Goods类表示商品
    现需要编写一个计算商品总价值的程序,现要求:1、定义一个表示商品的类:Goods,Goods类要包含:一个私有成员变量Stringname表示商品的名称;一个私有成员变量floatprice表示商品的价格,并定义setPrice(floatprice)方法用于修改商品价格;一个私有成员变量intcount表示商品的数量,并定......
  • C语言查找-----------BF算法&&KMP算法
    1.问题引入有一个主字符串,有一个子字符串,要求我们寻找子字符串在主字符串里面开始出现的位置;2.BF算法BF算法就是暴力算法,这个做法虽然效率不高,但是按照我们传统的思路依然能够得到结果,接下来我们使用C语言实现这个查找的过程;#include<stdio.h>#include<assert.h>#includ......
  • C语言rand、srand库函数生成随机数(附时间戳)
    前言:当我们想要用C语言写程序来获取一个随机数时,该如何获取呢?这里我们上百度搜索一下这里就有提到使用rand、srand、time库函数搭配来获取随机数,也许根据其所说我们已经可以获得随机数解决问题,但想问题不能只浮于表面,下面我们来深入认识一下rand、srand、time库函数。一、ra......