宏和函数的区别

  • 通常被应用于执行简单的算法,比如找出两个数中的最大值:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#define Max(x,y) x>y?x:y
int main()
{
	int a = 0;
	int b = 0;
	int c = 0;
	printf("Enter a:");
	scanf("%d", &a);
	printf("Enter b:");
	scanf("%d", &b);
	c=Max(a, b);
	printf("%d\n", c);
	system("pause");
	return 0;
}

代码运行如下:


这个代码不可以用函数完成?

当然可以用函数,只是宏比函数在这个代码中更加有优势:

1:代码非常简单,使用宏直接在编译期间就替换了c,而函数要调用以及返回,这些时间可能比代码执行的时间还要多;

2:宏可以用于整形,长整型,浮点型等可以用>来比较的类型,与类型无关;但是函数的参数必须声明为特定的类型;

  • 还可以干一些函数做不到的事情,比如宏可以出现类型,但是函数不可以。
#define MALLOC(num,type) (type*)malloc(num*sizeof(int))

malloc(10,int)即向内存申请10个类型为int型的内存;

当然宏也有劣势:

  1. 使用宏时,除非代码很短,否则会造成篇幅大度增长,比如宏有20行,被调用20次,就会使代码增加400行;
  2. 宏没有办法调试,比如由于宏少带括弧造成的运算错误,调试时没有办法确定错误的位置;
  3. 宏与类型无关,当然也就不够严谨;
  4. 宏会因为括号的问题导致程序出错;

带有副作用的宏:(包含i++,i--等)

#include<stdio.h>
#include<stdlib.h>
#define MAX(a,b) ((a)>(b)?(a):(b))
int main()
{
	int x = 5;
	int y = 8;
	int z = MAX(x++, y++);//后置++,先使用后加1;
	printf("x=%d y=%d z=%d ", x, y, z);
	system("pause");
	return 0;
}

这段代码我们期望输出x=6,y=9,z=8;

运行结果:


正是因为宏的副作用导致出错,预处理后:z=((x++)>(y++)?(x++):(y++))

后置++,先使用后++,5>8不成立x=6,y=9,输出z=9,y++变成10;

所有在使用宏时可能存在危险,导致不可估量的错误;

  • 一个简单的例题:使用宏将一个数的奇数位和偶数位互换
#include<stdio.h>
#include<stdlib.h>
#define exchange(a)  ((a&(0x55555555))<<1)|((a&(0xAAAAAAAA))>>1)
int main()
{
	int a = 5;               
	int b = exchange(a); //取出奇数位右移一位,偶数位左移一位
	printf("%d\n", b);
	system("pause");
	return 0;
}

代码思路:

取出奇数位:a&10101010101010101010101010101010

取出偶数位:a&01010101010101010101010101010101

奇数位右移一位到偶数位,偶数位左移一位到奇数位;

由于二进制数太多,会导致常量太大,所以可以将二进制改成十六进制;

运行如下:



猜你喜欢

转载自blog.csdn.net/zhao_miao/article/details/79949455