![更多课程](/zhuzhan/img/btn-course.png)
![选择中心](/zhuzhan/img/btn-center.png)
![logo](/zhuzhan/img/logo.png)
C/C++培训
达内IT学院
400-111-8989
![](/zhuzhan/images/weixin.jpg)
想必学过C的朋友们一定会记得一个基本的define使用原则,那就是#define 语句后面是不需要分号的,但是果真如此吗?
一个容易招打的例子:
首先必须明确,实际中写下面这样的代码是容易招打的,对于出题人,可能也会顺便骂一骂。不过骂归骂,该学的语法还是得学。下面的代码是读者在群里的一个提问相关代码:
#include<stdio.h>
#define A(x) x;x;x;x;
int main(void)
{
int n = 10;
A(A(printf("%d\n",n++)));
return 0;
}
输出结果:
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
在这里我们先不解释为什么输出上面的结果,如果你已经完全清楚了,也可以一起复习一下。
#define的用法
关于#define的用法,介绍的书籍和文章有很多,也有经常被拿来与typedef(参考《一句话帮你理解typedef用法》)以及const(参考《const关键字到底该怎么用?》)对比的,这里不展开,关于#define一些其他的用法,也不会涉及,只说明最基本的用法。
说起define,最简单明了的用法,就是字符串的简单替换,提高代码的可读性,并且一次修改,多处生效。
#include<stdio.h>
#define NUM 9
int main(void)
{
printf("%d\n",NUM);
return 0;
}
这个想必不用我多解释了,输出结果是9。实际上,等同于下面这样:
#include<stdio.h>
int main(void)
{
printf("%d\n",9);
return 0;
}
注意,#define语句那里并没有加分号,因为我们知道加上分号之后,是会报错的。
#include<stdio.h>
#define NUM 9;
int main(void)
{
printf("%d\n",NUM);
return 0;
}
编译报错:
$ gcc -o test test.c
test.c: In function ‘main’:
test.c:2:14: error: expected ‘)’ before ‘;’ token
#define NUM 9;
为什么会报错?你可能会说,这很明显啊,#define语句后面怎么可以有分号呢?说得是,不过真正的原因,并不是因为#define后面有分号,而在于它导致了不该有分号的地方有了分号:
#include<stdio.h>
int main(void)
{
printf("%d\n",9;);
return 0;
}
看见没有,9后面还有一个分号,你说能不报错吗?什么,这是我猜的?来来来,预编译(参考《hello程序是如何编译出来的》)给你看看:
$ gcc -E -o test.i test.c
$ tail -10 test.i
# 2 "test.c" 2
# 2 "test.c"
int main(void)
{
printf("%d\n",9;);
return 0;
}
现在信了吧?所以,总结一下普通用法的#define只是简单的字符串替换而已,所以对于下面这种题目,你应该容易理解了:
#include<stdio.h>
#define area(x) x*x //计算数的平方
int main(void)
{
int y = area(2+3);
printf("%d\n",y);
return 0;
}
替换嘛,area(x),其中x是2+3,那么得到:
2+3*2+3
因此得到结果11,而不是16。
所以你可能更多看到的会是下面这种:
#define area(x) (x)*(x)
这样得到的就会是:
(2+3)*(2+3)
就可以得到25了。
为什么一般来说#define后面没有分号?
其中通过前面的例子你也明白了,所谓#define语句后面一般没有分号的原因在于,将要替换的字符串还原之后,导致还原位置的语句出现问题,因此才使得后面不能有分号。
也就是说,如果替换之后,语法正常,其实是可以的(注意空格问题)。比如:
#include<stdio.h>
#define NUM 1024;
int main(void)
{
int a = NUM;
printf("%d\n",a);
return 0;
}
我在#define语句的后面加了个分号,替换到原处之后,语句变成了:
int a = 1024;;
显然这并不会有语法问题,只是显得非常累赘;并且这也只是碰巧不会有问题,像前面的例子那样还是会有问题。
真相大白
再回到最初的代码,想必你已经心里有数了。将#define定义的相关内容进行替换之后,得到的结果是下面这样的:
printf("%d\n",n++);printf("%d\n",n++);printf("%d\n",n++);printf("%d\n",n++);;printf("%d\n",n++);printf("%d\n",n++);printf("%d\n",n++);printf("%d\n",n++);;printf("%d\n",n++);printf("%d\n",n++);printf("%d\n",n++);printf("%d\n",n++);;printf("%d\n",n++);printf("%d\n",n++);printf("%d\n",n++);printf("%d\n",n++);;;
总结
本文并不鼓励你在实际中写这样的代码。只是通过这样的例子来加深对#define的用法。而#define语句之后是否有分号,视你自己的实际代码情况而定。当然,绝大多数时候是不需要的。而需要的时候,也请尽量保证代码的可读性良好。
填写下面表单即可预约申请免费试听!怕钱不够?可就业挣钱后再付学费! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!