更多课程 选择中心

C/C++培训
达内IT学院

400-996-5531

谁说#define语句后面不能有分号?

  • 发布:守望,Linux应用开发者
  • 来源:编程珠玑
  • 时间:2020-06-17 14:51

想必学过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语句之后是否有分号,视你自己的实际代码情况而定。当然,绝大多数时候是不需要的。而需要的时候,也请尽量保证代码的可读性良好。

预约申请免费试听课

填写下面表单即可预约申请免费试听!怕钱不够?可就业挣钱后再付学费! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!

上一篇:非常详细的 Linux C/C++ 学习路线总结
下一篇:关于C语言结构体用法中的坑你知道多少?

C语言宏定义的几种使用方法

C与C++内存管理避坑指南

C/C++代码规范注释有哪些讲究?

C语言中,全局变量滥用的后果竟如此严重?

Copyright © 2023 Tedu.cn All Rights Reserved 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有

选择城市和中心
黑龙江省

吉林省

河北省

湖南省

贵州省

云南省

广西省

海南省