【c语言】宏(#define、#和##和#undef)与函数比较

1.#define

1)定义标识符

ef:#define在预处理阶段替代所有的Max

#define Max 100
int main()
{
	printf("%d\n", Max);
	system("pause");
	return 0;
}

define定义标识符的时候,不要轻易在最后加;可能造成语法错误。
eg:

#define Max 100;

int main()
{
	int max = 0;
	if (1)
	{
		max = Max;
	}
	else
		max = -1;
	system("pause");
	return 0;
}

2)#define定义宏

#defien 机制包括一个规定,允许把参数替换到文本中,这个实现通常成为宏。
下面是宏的申明方式:
#define name( a ) stuff
其中a是一个由逗号隔开的符号表,它们可能出现在stuff中
注意
参数列表的左括号必须与name紧邻
eg:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>

#define MAX(X,Y)  X>Y?X:Y
int  main()
{
	int a = 10;
	int b = 20;
	int max = MAX(a, b);
	printf("%d", max);
	system("pause");
	return 0;
}

下面代码想输出64却不行思考解决方法:

#define MAX(X,Y)  X>Y?X:Y
#define S(x) x*x
int  main()
{
	int a = 10;
	int b = 20;
	int max = S(3+5);
	printf("%d", max);
	system("pause");
	return 0;
}

解决方法:在宏定义的两边加上一对括号,如下

#define MAX(X,Y)  X>Y?X:Y
#define S(x) (x)*(x)
int  main()
{
	int a = 10;
	int b = 20;
	int max = S(3+5);
	printf("%d", max);
	system("pause");
	return 0;
}

所以用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或临近操作符之间不可预料的相互作用;

3)define的替代

1.在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号,如果是,它们首先被替代
2.替代文本随后被插入到程序中原本文本的位置,对于宏,参数名被它们的值替代。
3.最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的服符号,如果是,就重复上述的处理过程

注意

  • 宏参数和#define定义中可以出现#define定义的变量,但是对于宏,不能出现递归
  • 当预处理搜索#define定义的符号的时候,字符串常量的内容并不被搜索

2.#和##和#undef

1)使用#可以把一个宏参数变为一个对应的字符串

eg:

#define Print(val,format)  printf("the value of "#val" is "format, val)
int main()
{
	int a = 9;
	Print(a, "%d");
	system("pause");
	return 0;
}

运行结果为:
这里写图片描述

2)##可以把位于它两边的符号合并为一个符号,它允许宏定义从分离的文本片段创建标识符

eg:

#define Cat(x,y) x##y
int main()
{
	int test38 = 10;
	printf("%d\n", Cat(test, 38));
	system("pause");
	return 0;
}

输出结果为10;

3.#undef

这个预处理指令用于移除一个指定的宏定义

格式:#undef NAME

3.宏和函数

有时候宏和函数可以完成相同的功能


  • 优点
    1.宏比函数在程序的规模和速度方面更胜一筹
    2.宏是类型无关的,可以适用于整形,长整形,浮点型等等类型。
    劣处
    1.每次使用宏的时候,一份宏定义的代码将插入到程序中,除非宏比较短,否则可能大幅度增加程序的长度
    2.宏是没法调试的
    3.宏类型无关,也不够严谨
    4.宏可能会带来运算符优先级的问题,导致程序容易出错
  • 函数
  • 优处
    1.函数代码 出现于一个地方,每次使用这个函数,都调用用一块程序代码
    2.函数参数只在函数调用时求值一次,它的结果值传递给函数,表达式的求值结果更容易猜测
    3.参数在函数被调用前只求值一次,在函数中的副作用并不会造成任何特殊的问题
    劣处
    1.存在函数调用返回的额外开销
    2.函数的参数是与类型无关的,如果参数的类型不同,就需要使用不同的函数,即使它们执行的任务是相同的

还有一些代码是使用函数无法实现的比如下面这个动态分配空间使用函数是无法实现的:


#include<stdio.h>
 
#define MALLOC(a, type)  \
	((type*)malloc((a)*sizeof(type)))//动态申请了10个type类型的空间
 
int main()
{
	int *p = MALLOC(10, int);  //給指针p动态分配了10个int类型的空间

       free(p);
	return 0;
}

因为宏的第二个参数是一个类型,类型可以作为宏的参数进行传递,不可以作为函数的参数进行传递。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值