- 宏通常被应用于执行简单的算法,比如找出两个数中的最大值:
#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型的内存;
当然宏也有劣势:
- 使用宏时,除非代码很短,否则会造成篇幅大度增长,比如宏有20行,被调用20次,就会使代码增加400行;
- 宏没有办法调试,比如由于宏少带括弧造成的运算错误,调试时没有办法确定错误的位置;
- 宏与类型无关,当然也就不够严谨;
- 宏会因为括号的问题导致程序出错;
带有副作用的宏:(包含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
奇数位右移一位到偶数位,偶数位左移一位到奇数位;
由于二进制数太多,会导致常量太大,所以可以将二进制改成十六进制;
运行如下: