• STM32学习及应用笔记二:一次运算符优先级造成的错误


        本人在最近一个项目的开发中,出现一个应为疏忽运算符优先级造成的问题,检查了很久才发现问题,所以觉得运算符的优先级问题还是有必要再研究一下。具体的问题是这样的,我采集了传感器的原始数据,然后会对数据进行一些处理,在其中的一种条件下会对一个数进行左移几位并加上一个数。类似的操作在其他地方也有,但只在这个地方忘记了一个括号,所以得出了结果总是存在偏差,只好从头开始查找,花了不少时间才发现这出错误。

        其实本人平时还是非常注意代码规范的,但也有一时疏忽的,确实运算符的优先级有时候让人迷惑。下面我们简单的总结一下C语言中运算符的优先级问题。C语言中各运算符的优先级如下表所示:

    优先级

    运算符

    名称或含义

    使用形式

    结合方向

    说明

    1

    []

    数组下标

    数组名[常量表达式]

    左到右

     

    ()

    圆括号

    (表达式)/函数名(形参表)

     

    .

    成员选择(对象)

    对象.成员名

     

    ->

    成员选择(指针)

    对象指针->成员名

     

    ++

    后置自增运算符

    ++变量名

    单目运算符

    --

    后置自减运算符

    --变量名

    单目运算符

    2

    -

    负号运算符

    -表达式

    右到左

    单目运算符

    (类型)

    强制类型转换

    (数据类型)表达式

     

    ++

    前置自增运算符

    变量名++

    单目运算符

    --

    前置自减运算符

    变量名--

    单目运算符

    *

    取值运算符

    *指针变量

    单目运算符

    &

    取地址运算符

    &变量名

    单目运算符

    !

    逻辑非运算符

    !表达式

    单目运算符

    ~

    按位取反运算符

    ~表达式

    单目运算符

    sizeof

    长度运算符

    sizeof(表达式)

     

    3

    /

    表达式/表达式

    左到右

    双目运算符

    *

    表达式*表达式

    双目运算符

    %

    余数(取模)

    整型表达式/整型表达式

    双目运算符

    4

    +

    表达式+表达式

    左到右

    双目运算符

    -

    表达式-表达式

    双目运算符

    5

    << 

    左移

    变量<<表达式

    左到右

    双目运算符

    >> 

    右移

    变量>>表达式

    双目运算符

    6

    大于

    表达式>表达式

    左到右

    双目运算符

    >=

    大于等于

    表达式>=表达式

    双目运算符

    小于

    表达式<表达式

    双目运算符

    <=

    小于等于

    表达式<=表达式

    双目运算符

    7

    ==

    等于

    表达式==表达式

    左到右

    双目运算符

    !=

    不等于

    表达式!= 表达式

    双目运算符

    8

    &

    按位与

    表达式&表达式

    左到右

    双目运算符

    9

    ^

    按位异或

    表达式^表达式

    左到右

    双目运算符

    10

    |

    按位或

    表达式|表达式

    左到右

    双目运算符

    11

    &&

    逻辑与

    表达式&&表达式

    左到右

    双目运算符

    12

    ||

    逻辑或

    表达式||表达式

    左到右

    双目运算符

    13

    ?:

    条件运算符

    表达式1? 表达式2: 表达式3

    右到左

    三目运算符

    14

    =

    赋值运算符

    变量=表达式

    右到左

     

    /=

    除后赋值

    变量/=表达式

     

    *=

    乘后赋值

    变量*=表达式

     

    %=

    取模后赋值

    变量%=表达式

     

    +=

    加后赋值

    变量+=表达式

     

    -=

    减后赋值

    变量-=表达式

     

    <<=

    左移后赋值

    变量<<=表达式

     

    >>=

    右移后赋值

    变量>>=表达式

     

    &=

    按位与后赋值

    变量&=表达式

     

    ^=

    按位异或后赋值

    变量^=表达式

     

    |=

    按位或后赋值

    变量|=表达式

     

    15

    ,

    逗号运算符

    表达式,表达式,…

    左到右

    从左向右顺序运算

    在上表中,同一优先级的运算符,运算次序由结合方向所决定。当然大部分的运算符都是左结合的,与我们的常识一致,但要记住有一部分运算符是右结合的,实在记不住也没有关系,我们可以在编写代码时以( )加以规范。

    当然,事情并非我们希望的那么简单。在上表中,如果优先级同为1 的几种运算符同时出现时,想要确定表达式的优先级就会让大家,特别是初学者感到迷惑不解。接下来我们整理了一些容易出错的情况:

    优先级问题

    表达式

    想要的结果

    实际结果

    .的优先级高于*

    *p.f

    指针p所指向的对象的某一字段f,即:(*p).f

    对p取f偏移作为指针,然后进行解除饮用操作,即:*(p.f)

    []的优先级高于*

    int *p[]

    P是指向int数组的指针,即:int (*p)[]

    P是元素为指向int的指针的数组,即:int *(p[])

    函数()优先级高于*

    int *p()

    p是个函数指针所指函数返回值是int,即:int (*p)()

    P是个函数,返回值是int   *,即:int *(p())

    ==和!=优先级高于位操作

    (val&mask!=0)

    (val&mask)!=0

    val&(mask!=0)

    ==和!=优先级高于赋值操作

    c=getchar()!=EOF

    (c=getchar())!=EOF

    c=(getchar()!=EOF)

    算术运算符高于移位运算符

    msb<<4+lsb

    (msb<<4)+lsb

    msb<<(4+lsb)

    逗号运算符的优先级最低

    i=1,2

    i=(1,2)

    (i=1),2

    当然,熟记上面这个表中的东西可以减少犯错,但归根到底,最关键是多写代码多使用,熟练了自然就没问题了。

  • 相关阅读:
    4.使用webpack-dev-server工具实现自动打包编译的功能
    3.使用webpack配置文件webpack.confg.js配置打包文件的入口和出口
    2.webpack最基本的使用方式
    启动nginx 80端口被占用:tcp 0 0 127.0.0.1:80 127.0.0.1:34932 TIME_WAIT
    template标签就相当于React中的fragment
    初窥AST
    npm 中的 --
    你不知道的环境变量(转)
    非捕获分组 正向预查 与反向预查
    border-radius 如何计算
  • 原文地址:https://www.cnblogs.com/foxclever/p/6936953.html
Copyright © 2020-2023  润新知