【 C 】最容易误判的优先级问题

举报
李锐博恩 发表于 2021/07/15 07:59:32 2021/07/15
【摘要】 这篇博文有没有必要呢? 关于优先级问题,其实也不必太强求,我们提倡使用()来代表优先级,让程序简单易懂,对自己以及对他们都好。可是呢?有的时候你不得不阅读一些劣质的代码,把一些表达式硬生生地写成了玄学! 为了让自己更强大,我们还是总结一下吧,以免遇到! 最后,强调下自己最好不要写这种代码!除非阅读代码的人和你有仇,并且你可自己有仇! 这里声明下,关于一些表达式的解释方...

这篇博文有没有必要呢?

关于优先级问题,其实也不必太强求,我们提倡使用()来代表优先级,让程序简单易懂,对自己以及对他们都好。可是呢?有的时候你不得不阅读一些劣质的代码,把一些表达式硬生生地写成了玄学!

为了让自己更强大,我们还是总结一下吧,以免遇到!

最后,强调下自己最好不要写这种代码!除非阅读代码的人和你有仇,并且你可自己有仇!

这里声明下,关于一些表达式的解释方式,我是按照《C与指针》中的方法解释的,我在其他博文中也总结了,参看:【 C 】对指针表达式的个人总结与思考

 


num1:

int  *ap[];

其实我们可以分析下这个声明的含义,首先我们必须先知道下标引用操作符[]的优先级高于间接引用操作符,这样首先ap[]是一个数组,然后对其元素解引用(间接访问),因此我们可以断定这是一个数组,且数组的元素是指针类型,所以这个声明是一个指针数组。

我们改善的写法应该为:

int  *( ap[] );

其实这个例子还比较简单,所以,不加括号也没问题,一个有经验的程序员应该不会误判!

如果我们误以为间接访问操作符*的优先级高于下标引用操作符[],我们就会把这个声明,误判为:int  (*ap)[],如果是这样的话就出大事了,我们来分析下,这个表达式是什么意思?

首先ap是一个指针,对其解引用后呢,又可以进行下标访问操作,可见这是一个指向数组的指针的声明。

关于指针数组和指向数组的指针,二者确实容易混淆,我有相关博文对此进行专门介绍:

【 C 】指针数组案例分析(const的作用)

【 C 】指向数组的指针(数组指针)(行指针)


num2:

int *fp();

这是一个猛一看很令人头疼的声明,fp到底是什么?

我们不妨一起分析下:我们必须知道的优先级关系是函数()高于间接访问*。这样的话,这个表达式首选执行的是fp(),很显然这是一个函数,其次,函数存在一个返回值,对返回值进行解引用(间接访问)得到一个int类型的值,可见,这是一个指针函数,函数的返回值是一个指向int类型的指针常量。

可见,上述表达式这样声明会更容易辨认些:

int *( fp() );

同样,这种表达式怪怪的,也许是因为大家都了解这个优先级别的原因或者函数指针会写成这样的形式:int (*fp)();所以认为不至于混淆!

可是我们常常会误以为这是一个函数指针,也就是把表达式误以为等价于:int (*fp)();我们来分析这个表达式是什么含义:首先执行的是

*fp,那么可以断定fp就是一个指针了,其次又可以进行函数引用(),那么根据我们的知识可知,这是一个指向函数的指针,函数定义过后,是有一个地址专门存放的,那有一个指向该函数的指针也不为过吧。该函数还是一个返回值为int类型的值的函数。

程序中的每个函数都位于内存中的某个位置,所以存在指向那个位置的指针是完全可能的 --------------------- 本文来自 李佳姗 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/Reborn_Lee/article/details/82694875?utm_source=copy

关于函数指针,我也有专门的博文介绍:【 C 】初识函数指针


num3

(val & mask != 0)

多少人会和我一样认为是这样的呢?(val & mask) != 0。

这是不对的,它的真正含义是: val & (mask != 0),这是因为== 和 != 的优先级高于位操作符。

可见,如果写成:

val & (mask != 0)

可读性会更高 。这也正是我们所提倡的写法。


num4

c = getchar() != EOF

我们可能会认为其等价于:

( c = getchar() ) != EOF

其实不然,因为==和!=的优先级高于赋值操作符,它等价于:

c =( getchar() != EOF)


num5

msb << 4 + lsb

写成这个样子真的很无奈,它让我们无法判别,我们可能会以为它等价于:

(msb << 4)+ lsb

但事实上,算术操作符的优先级高于移位操作符,所以它等价于:

msb << (4 + lsb)


num6

逗号运算符在所有操作符中优先级最低,所以如下表达式:

i = 1, 2

等价于:

(i = 1), 2


num7

*p.f

.的优先级高于*,所以等价于

*(p.f)

即对p取f偏移,作为指针,然后进行间接访问。

p应该是一个结构体变量,然后直接访问对结构成员进行访问p.f,由于成员是一个指针,所以对其进行间接访问操作得到该指针指向的值。

这个表达式让我们明白,我们不要把这个表达式等价成了这个:

(*p).f

首先,p是一个指向结构变量p的指针,然后对其解引用,得到结构体变量,然后间接访问其成员。这个过程看起来很不直观,为了解决这个问题,我们引入了结构体的间接访问->,用:

p ->f

来清晰的表达。

 

 

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/82825648

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。