C语言之#define的一些注意事项

C语言之#define的一些注意事项

  • #define
    • 1.#define 定义标识符
    • 2.#define 定义宏
    • 3.带副作用的宏
    • 4.宏和函数的简单比较
      • 宏的优点
      • 宏的缺点
    • 5.命名约定

#define

1.#define 定义标识符

#define MAX 100
#define MIN 1 
int main()
{
	int i = MAX;
	int q = MIN;
	printf("i=%d q=%d\n", i, q);
	return 0;
}

C语言之#define的一些注意事项_第1张图片
#define 不止可以定义常数

#define do_forever for(; ; )
#define n printf(“hello world\n”)

这里可能有人会有疑问为什么最后不加;

#define MAX 100;
#define MIN 1 ;
#define n printf("hello world\n") ;

int main()
{
	int i = MAX;
	int q = MIN;
	printf("i=%d q=%d\n", i, q);
	n;
	return 0; 
}

经过预编译就会变成 int i=100;; int q=1;;
这个时候代码还是可以运行的
C语言之#define的一些注意事项_第2张图片

那我们把代码改一下

#define MAX 100;
#define MIN 1 ;
#define n printf("hello world\n") ;

int main()
{
	int i = MAX;
	int q = MIN;
	if (i == 100)
		n;
	else
	{
		printf("错误\n");
	}
	printf("i=%d q=%d\n", i, q);
	n;
	return 0;
}

再运行一下,这时候就会报错
在这里插入图片描述
原因是什么呢?
仔细观察一下if语句,我们不难发现

代码变成
if (i == 100)
printf(“hello world\n”) ;
;
else
{
printf(“错误\n”);
}

很明显多了个;

因此,最好#define 最后不要加; 容易发生问题

2.#define 定义宏

#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)。
下面是宏的申明方式:

#define name( parament-list ) stuff
其中的 parament-list 是一个由逗号隔开的符号表,它们可能出现在stuff中。
例如:
#define a(n) n*n

定义宏的过程中也有一下要注意的

#define a(n) n*n

int main()
{
	printf("%d\n", a(1 + 2));
	return 0;
}

相信不少人会认为结果是9,让我们来运行一下
C语言之#define的一些注意事项_第3张图片
结果为什么是5而不是9呢?

在预编译过程中,上面代码会变成
printf(“%d\n”, 1+2*1+2);

由此我们可以得知,上面的#define最好改成

#define a(n) (n)*(n)

我们再运行一次
C语言之#define的一些注意事项_第4张图片
这下就变成9了

那这样改就没问题了吗?
我们再来看下面的代码

#define a(n) (n)+(n)

int main()
{
	printf("%d\n",10*a(1 + 2));
	return 0;
}

运行一下
C语言之#define的一些注意事项_第5张图片
居然不是我们想要的60,而是33,不过相信大家都已经发现了问题的所在

在预编译过程中,上面代码会变成
printf(“%d\n”,10*(1 + 2)+(1+2));
自然就是33了

相信大家都知道要怎么改了

#define a(n) ((n)+(n))

int main()
{
	printf("%d\n",10*a(1 + 2));
	return 0;
}

再运行一下
C语言之#define的一些注意事项_第6张图片
这下就是60了

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

这里还有一个小的点,

#define name( parament-list ) stuff
参数列表的左括号必须与name紧邻。
如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。

3.带副作用的宏

当宏参数在宏的定义中出现超过一次的时候,如果参数带有副作用,那么你在使用这个宏的时候就可能出现危险,导致不可预测的后果。副作用就是表达式求值的时候出现的永久性效果。

例如:

#define a(n,m)  ((n)>(m)?(n):(m)) 

int main()
{
	int i = 1;
	int j = 2;
	int k=a(i++,j++);
	printf("%d\n", i);
	printf("%d\n", j);
	printf("%d\n", k);
	return 0;
}

运行一下
C语言之#define的一些注意事项_第7张图片
我们来分析一下为什么是2 4 3

在预编译过程中,上面代码会变成
int k=((i++)>(j++)?(i++):(j++)

这里因为j>i,所以j++了2次

所以遇到这种情况要小心会不会带来副作用

4.宏和函数的简单比较

宏的优点

  1. 宏比函数在程序的规模和速度方面更胜一筹
  2. 函数要声明特定的类型,宏没有类型检测

宏的缺点

  1. 宏没法调试
  2. 宏与类型无关,因此不够严谨
  3. 宏可能会带来运算符优先级等问题,导致程序容易出错
  4. 宏不能递归

5.命名约定

一般来讲函数的宏的使用语法很相似。所以语言本身没法帮我们区分二者。因此我们平时的习惯是:

把宏名全部大写
函数不要全部大写

你可能感兴趣的:(windows,c语言)