是否任何情况下宏定义的max/min 都比函数定义的max/min 更快

很多时候,处于减少函数栈帧的申请开销,一些奇怪的建议(尤其是出于搞ACM的经验 会 诱导 我们把max/min这种小函数定义为宏。

通常情况下,这种优化策略是没得问题的,但是有时宏的简单替换不但没法减少开销,反而会大大增加开销的。

这个例子是我从《编程珠玑》看来的。

求一个数组中的最大值。

方法一

把max定义为函数

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int max(int a, int b)
{
	return a > b ? a : b;
}

int argmax(int* a, int n)
{
	if (n == 1)
	{
		return a[0];
	}
	return max(a[n - 1], argmax(a, n - 1));
}
#define N 28
int a[N] = { 0 };
int main()
{
	srand(time(0));

	for (int i = 0; i < N; i++)
	{
		a[i] = N-i;
	}
	long long int start = time(0);
	int m = argmax(a, N);
	long long int end = time(0);
	printf("[%lld,%lld]:%d\n", start, end, m);
	system("pause");
	return 0;
}

运行结果:基本在毫秒级就得到了结果。

方法二:
把max定义为宏

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define max(a,b) (a)>(b)?(a):(b)

//int max(int a, int b)
//{
//	return a > b ? a : b;
//}

int argmax(int* a, int n)
{
	if (n == 1)
	{
		return a[0];
	}
	return max(a[n - 1], argmax(a, n - 1));
}
#define N 28
int a[N] = { 0 };
int main()
{
	srand(time(0));

	for (int i = 0; i < N; i++)
	{
		a[i] = N-i;
	}
	long long int start = time(0);
	int m = argmax(a, N);
	long long int end = time(0);
	printf("[%lld,%lld]:%d\n", start, end, m);
	system("pause");
	return 0;
}

运行结果:运行了8s才出结果。。。。

为何???

差别如此巨大这是为何呢???
本质是因为宏的 无脑替换。

如果是函数实现,则max(a[n-1],argmax(a,n-1)) 中,只计算一次argmax(a,n-1] 然后把结果作为参数送给max函数。

如果是宏实现:
max(a[n-1],argmax(a,n-1))其实展开后是a[n-1] > argmax(a,n-1)? a[n-1]:argmax(a,n-1) ,第n层需要计算两次 argmax(a,n-1),第n-1层需要计算4次argmax(a,n-2) 这样下去,其实是 O ( 2 n ) O(2^n) 求一个数组的最大值。

这个例子说明,有的时候宏还真不一定函数更快。宏的快更多是鼠目寸光式的快,它只引入短期的加速,但是如果宏的参数是函数调用,那么就要特别注意了!!!因为宏的无脑替换,有可能明明只需计算一次的参数,在宏的展开却要计算多次。

发布了307 篇原创文章 · 获赞 268 · 访问量 56万+

猜你喜欢

转载自blog.csdn.net/jmh1996/article/details/102674938