想必学过C的朋友们一定会记得一个基本的使用原则,那就是# 语句后面是不需要分号的,但是果真如此吗?

一个容易招打的例子

首先必须明确,实际中写下面这样的代码是容易招打的define,对于出题人,可能也会顺便骂一骂。不过骂归骂,该学的语法还是得学。下面的代码是读者在群里的一个提问相关代码:

//来源:公众号【编程珠玑】
//作者:守望先生
//https://www.yanbinghu.com
#include
#define A(x) x;x;x;x;
int main(void)
{
    int n = 10;
    A(A(printf("%dn",n++)));
    return 0;
}

输出结果:

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

在这里我们先不解释为什么输出上面的结果,如果你已经完全清楚了,也可以一起复习一下。

#的用法

关于#的用法,介绍的书籍和文章有很多,也有经常被拿来与(参考《一句话帮你理解用法》)以及const(参考《const关键字到底该怎么用?》)对比的,这里不展开,关于#一些其他的用法,也不会涉及,只说明最基本的用法。

说起,最简单明了的用法,就是字符串的简单替换,提高代码的可读性,并且一次修改,多处生效。

//来源:公众号【编程珠玑】
//作者:守望先生
#include
#define NUM 9
int main(void)
{
    printf("%dn",NUM);
    return 0;   
}

这个想必不用我多解释了,输出结果是9。实际上,等同于下面这样:

#include
int main(void)
{
    printf("%dn",9);
    return 0;   
}

注意,#语句那里并没有加分号,因为我们知道加上分号之后,是会报错的。

#include
#define NUM 9;
int main(void)
{
    printf("%dn",NUM);
    return 0;   
}

编译报错:

$ gcc -o test test.c
test.c: In function ‘main’:
test.c:2:14: errorexpected ‘)’ before ‘
;’ token
 #define NUM 9;

为什么会报错?你可能会说,这很明显啊,#语句后面怎么可以有分号呢?说得是,不过真正的原因,并不是因为#后面有分号,而在于它导致了不该有分号的地方有了分号:

#include
int main(void)
{
    printf("%dn",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("%dn",9;);
    return 0;
}

现在信了吧?

所以,总结一下普通用法的#只是简单的字符串替换而已,所以对于下面这种题目,你应该容易理解了:

/*来源:公众号【编程珠玑】*/
//作者:守望先生
#include
#define area(x) x*x  //计算数的平方
int main(void)
{
    int y = area(2+3);
    printf("%dn",y);   
    return 0;
}

替换嘛,area(x),其中x是2+2,那么得到:

2+3*2+3

因此得到结果11,而不是16。

所以你可能更多看到的会是下面这种:

#define area(x) (x)*(x)

这样得到的就会是:

(2+3)*(2+3)

就可以得到25了。

为什么一般来说#后面没有分号?

其中通过前面的例子你也明白了define,所谓#语句后面一般没有分号的原因在于,将要替换的字符串还原之后,导致还原位置的语句出现问题,因此才使得后面不能有分号。

也就是说,如果替换之后,语法正常,其实是可以的(注意空格问题)。比如:

//来源:公众号【编程珠玑】
//作者:守望先生
#include
#define NUM 1024;
int main(void)
{
    int a = NUM;
    printf("%dn",a);   
    return 0;
}

我在#语句的后面加了个分号,替换到原处之后,语句变成了:

int a = 1024;;

显然这并不会有语法问题,只是显得非常累赘;并且这也只是碰巧不会有问题,像前面的例子那样还是会有问题。

真相大白

再回到最初的代码,想必你已经心里有数了。将#定义的相关内容进行替换之后,得到的结果是下面这样的:

    printf("%dn",n++);printf("%dn",n++);printf("%dn",n++);printf("%dn",n++);;printf("%dn",n++);printf("%dn",n++);printf("%dn",n++);printf("%dn",n++);;printf("%dn",n++);printf("%dn",n++);printf("%dn",n++);printf("%dn",n++);;printf("%dn",n++);printf("%dn",n++);printf("%dn",n++);printf("%dn",n++);;;

总结

本文并不鼓励你在实际中写这样的代码。只是通过这样的例子来加深对#的用法。而#语句之后是否有分号,视你自己的实际代码情况而定。当然,绝大多数时候是不需要的。而需要的时候,也请尽量保证代码的可读性良好。

- END -


限时特惠:
本站持续每日更新海量各大内部创业课程,一年会员仅需要98元,全站资源免费下载
点击查看详情

站长微信:Jiucxh

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注