嵌入式学习一阶段——C语言:运算符与表达式

运算符与表达式

C语言提供了所有你希望编程语言应该拥有的操作符,他甚至提供一些你意想不到的操作符。
事实上,C语言之所以被很多人认为它很难精通就是因为它品种繁多的操作符。
它的这个特点也是其他语言无法抗衡价值

什么是运算符

顾名思义,就是说运算符用来表示某种运算的符号
​
几目运算符?表示这个运算符要带几个操作数
    单目运算符: 该运算符只需要一个操作数 eg:++ --
    双目运算符: 该运算符只需要两个操作数 eg:+ - *
    三目运算符: 该运算符只需要三个操作数 eg:a>b?a:b
​
结合性:  决定先算哪个操作数的问题
    从左到右 还有 从右到左
    eg:
        a+b
        b+a
         在C语言中,含义是不一样的
        + 结合性: 从左到右
    eg:
​
int i =5 , j = 6;
        int a;
        a = (i++) + (i+j); //17
​
int i =5 , j = 6;
        int b;
        b = (i+j) + (i++); //16
​
int i =5 , j = 6;
        int a;
        int b;
        a = (i++) + (i+j); //17
        b = (i+j) + (i++); //18
​
int i =5 , j = 6;
        int a;
        int b;
        a = (++i) + (i+j); //18
        b = (i+j) + (++i); //19
​
i++ ====> i = i+1
​
运算符的优先级:
            在含有多个运算符的表达式中,决定先算哪个运算符,后算哪个运算符的问题
            eg:
                a+b*c
        单目运算符 > 算术运算符 > 关系运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符

什么是表达式

表达式就是表达某个意思的式子
在C语言中,一般来说,表达式是指用运算符连接操作数的式子
    3+5
eg:
    sb250
    i love you
    520
合法的表达式就一定会有一个值,因为任何表达式都需要表达某个意思

运算符的分类

算术运算符

算术运算符:进行算术运算的运算符
++ -- : 单目运算符
+ - * / % : 双目运算符
    + - * / : 只需要你的操作数是一个数(整数或者小数都可以)
    % : 要求操作数必须是整数
    ++ -- : 小数,浮点型
eg:
    3+5 = 8
    double + int ===》 double
    3.0 + 5 = 8.0
​
int a,b;
    a + b;
​
double f1 , f2;
    f1+f2;
​
3.5 % 3 ==== error
    % 表示取余
​
5/4 == 1
​
5.0 / 4 = 1.25
double / int   ===> double / double = double
​
(double)(3/2) = 1.0
    (double)3/2 = 1.5
    3/2.0 = 1.5
​
用C语言的表达式来表达数学表达式 a/b
        (double) a/b
        1.0*a / b
​
% 求余数
        5 % 4 === 1
        6 % 7 === 6
​
    ++(自增)运算符,单目运算符,要求操作必须是一个左值
    --(自减)运算符,单目运算符,要求操作必须是一个左值

左值 和 右值

在这里介绍一下
    为了理解一些操作数存在的限制,你必须要理解左边和右值之间区别。
​
左值就是赋值符号(=)左边的东西,右值就是赋值符号右边的东西
​
eg:
    a = b + 25;
    a 就是 左值, b+25 就是右值
    他们两个可以互换吗??
    b + 25 = a;
    原先用作左边的a此时变成了右值,因为每个位置它是不是肯定包含一个值,然后 b+25 不能作为一个左值,
    因为它没有表示一个特定位置,因此,这个语句是非法!
        注意当计算机去计算 b+25 的时候,它的结果必然保存在机器的某个位置,但是我们作为程序员没有办法来预测到这个位置在什么地方!
​
5++;    error    i++ === > i = i+1
(a+b)++;    error
​
表达式的值      做完表达式后的值
i++         i               i+1
++i        i+1             i+1
i--         i               i-1
--i        i-1               i-1

关系运算符

这一类运算符用于测试操作数之间的各种关系的,c语言提供所有常见的关系运算符
不过,这一组操作符里面有一个大大的陷阱
这一组操作符:
    >  >=  <  <=  !=  ==
​
前面四个操作符的功能你一看就知道是什么意思??
!= 操作符用来测试 ”不等于“
而== 操作符用于测试”等于“
​
关系表达式:用关系运算符连接起来的式子,如: a < b    8 < 7
    关系表达式的值:
        关系成立 : 1
        关系不成立 : 0
​
eg:
    5 > 4   1
    3 <= 4  1
    5 > 7  0
    3+5 < 7*8
(3+5) < (7*8)
8 < 56  ----> 1
​
5 > 4 > 3  这个东西是一个合法的关系表达式
        1 > 3  ----> 0
​
在C语言中, 5>4>3 这个表达式和数学5>4>3的表达式不一样
    (1)、在C语言中,5>4>3 ===> 1>3
    (2)、数学上,5>4>3
            5>3 并且 4>3
温馨提示:
    如果说下面这个问题不是C新手最常见的问题,那么它至少也是令人恼火一个错误!!!
    绝大部分其他的语言使用 = 操作符来进行比较 相等性 。在C语言中,你必须要用== 来进行比较,单个= 是赋值
    这个的陷阱在于: 在测试相等性的时候出现赋值符号也是合法的!! 它不是一个语法错误
        if(a==b)
​
if(a=b)

逻辑运算符

!     逻辑非       单目运算符          ”取反“
&&    逻辑与       双目运算符           ”并且“  从左到右
||    逻辑或       双目运算符           ”或者“  从左到右
​
逻辑表达式:用逻辑运算符连接起来的式子,逻辑表达式
    逻辑表达式的值:
        逻辑为真: 1 (非0)
        逻辑为假: 0
eg:
    int a = 4 , b = 5;
        a&&b; ===== 1
        a||b; ===== 1
        !a||b; ===== 1
        !a&&b; ===== 0
    5>3 && 8 < 4 - !0 
    5>3 && 8 < 3
    1 && 0     =====> 0
练习
分析如下程序的输出结果
    int a , b , c ,d , m ,n;
    a=1 ;
    b=2 ;
    c=3;
    d=4;
    m=1;
    n=1;
    (m=a>b)&&(n=c>d);
    printf("%d %d %d %d %d %d",a,b,c,d,m,n);
​
    C语言运算符是”惰性运算“
    (1)、a&&b&&c
        只有当a为真的时候,才会去判断b
        同时a和b都为真的时候,才会去判断c
    (2)a||b||c
        只要当a为真的时候,那么就不会再去判断b和c的值了
        只有当a 为假的时候,才需要去判断b 的值
        当b 为假的时候,才需要去判断c 的值
    
    in a word ,如果你实现就知道表达式的值 了,那么后面的运算符或者表达式就不需要去指向了!!!因为没有这个必要了
练习
(1)、用逻辑表达式来判断y(年份)是否为 闰年
    a、可以被4整除,但是不能被100整除
    b、可以被4整除,又可以被400整除
        (a)||(b)
        a:(y%4 == 0 && y%100 !=0)
        b:(y%4 == 0 && y%400 ==0)
        (y%4 == 0 && y%100 != 0)||(y%4 == 0 && y%400 == 0)
(2)、用逻辑表达式来判断y(年份)是否为非闰年
    int u  =  !((a)||(b))

位运算符

位运算符是按bit为展开来进行运算,位运算符要求操作数必须是一个整数(兼容的整数),因为在进行位运算时,需要把操作数按bit展开。”按每一个bit位来进行操作的“
​
&  按位与
|  按位或
^  按位异或
​
~  按位取反
>> 按位右移
<< 按位左移
​
除了 ~ 是单目运算符之外,其他的位运算符全部是双目运算符,结合性是从左到右的,位运算的操作数只能是整型。所有的位运算都需要把操作数变成bit位序列,然后进行操作
按位取反 ~
1 --->  0
0 --->  1

3:0000 0011 ~3:1111 1100

练习
int a = ~(-3);
3:
    0000 0011
取反:   1111 1100 
+1 --> -3:    1111 1101
    
~   0000 0010  ====>2
printf("%d\n",a); //2
printf("%u\n",a); //2
​
int a = !(-3)
printf("%d\n",a); //0
printf("%u\n",a); //0
!(非0) ==== 0
​
NOTE:
    要注意 ~(按位取反) 和 !(逻辑非) 的区别
        !(3+5) ==== 0
        ~ (3+5) ==== ~8
按位与 &

a & b a b a&b 1 1 1 1 0 0 0 1 0 0 0 0

& 如果两个bit位都为1,结果才为1,否则为0

eg: 3 & 5 00000000 00000000 00000000 00000011 00000000 00000000 00000000 00000101 00000000 00000000 00000000 00000001 =====》1

3 & 7
00000000    00000000    00000000    00000011
00000000    00000000    00000000    00000111
00000000    00000000    00000000    00000011 ======》3
​
3&&5 ====》 1
5&&7 ====》1

NOTE: 注意&(按位与)与&&(逻辑与)的区别

练习
假设有一个整型变量 a , 要把 a 的第5个bit,变为0 其他的bit不变,你该如何操作!!
int a;
a = a&~(1<<5)

结论: 一个bit位 与 0 进行按位与&操作,结果为0 X & 0 ==== 0 when x == 1 , 1&0 == 0 when x == 0 , 0&0 == 0

一个bit位 与 1 进行按位与&操作,结果保留原来的值
    X & 1 == X
    when x ==1 , 1 & 1 == 1;
    when x ==0 , 0 & 1 == 0;
按位或 |

a | b a b a|b 1 1 1 1 0 1 0 1 1 0 0 0

按位或,只要有一个bit操作数为1,结果就为1

3|5 === 7 
00000000    00000000    00000000    00000011
00000000    00000000    00000000    00000101
00000000    00000000    00000000    00000111 ====》7
​
3||5 == 1

NOTE: 要区分 | 按位或 和 || 逻辑或的区别

练习: 假设有一个整型变量a, 要把a 的第28个bit,变为1 。其他位不变,你该如何操作!? a = a | (a << 27)

结论: 一个bit位 与 1 进行 ”按位或|“的一个操作,结果为1 X | 1 ==== 1 一个bit位 与 0 进行 ”按位或|“的一个操作,结果保留原来的值 X | 0 ==== X

按位异或 ^
"异或":求异,不同为1 ,相同就为0 

a ^ b a b a^b 1 1 0 1 0 1 0 1 1 0 0 0 eg: 3^5 === 6 00000000 00000000 00000000 00000011 00000000 00000000 00000000 00000101 00000000 00000000 00000000 00000110 ===>6

练习: 假设有一个整型变量a,要把a的第5个bit保留,其他bit取反,阁下该如何应对? a = a ^~(1<<5)

结论: 一个 bit 位 与 0 进行”按位异或 ^“,保留原值 x ^ 0 === x

一个 bit 位 与 1 进行”按位异或 ^“,结果相反
    x ^ 1 === ~x
按位右移
X >> N 把 x 按照bit位整体往右边移动n位!
    低位右移后,舍弃   
        0000 1111 ----> xxxx 0000   (右移四位)
            高位补什么??  xxxx是什么??
            对于无符号数,高位就全部补0
            对于有符号数,高位就全部补原来的符号位
按位左移
双目运算符,按bit位左移
    2 << 1 ===> 4   0000 0010 ===> 0000 0100
    高位左移,舍弃,低位就补0
    如果左移动舍弃的高位是0,那么左移n位,表示的结果就乘以2的n次方
练习:
分析如下程序的输出结果!!
(1)、
    int  a=-1;
    a = a >> 31;
    printf("%d\n",a); //-1
    printf("%u\n",a); //2^32-1
    -1 :
        00000000 00000000 00000000 00000001
        11111111 11111111 11111111 11111110
        11111111 11111111 11111111 11111111 
        
(2)、
    unsigned int  a=-1;
    a = a >> 31;
    printf("%d\n",a); //1
    printf("%u\n",a); //1
​
    -1 :
        00000000 00000000 00000000 00000001
        11111111 11111111 11111111 11111110
        11111111 11111111 11111111 11111111
        00000000 00000000 00000000 00000001
​
(3)、
    char a = -1;
    int b = a >> 31;
    printf("%d\n",b); //-1
    printf("%u\n",b); //2^32-1
​
    a : 
       -1 :
          1111 1111
    a >> 31 
        char --> int 
            11111111 11111111 11111111 11111111 >> 31
            11111111 11111111 11111111 11111111
​
(4)、
    unsigned char a = -1;
    int b = a >> 31;
    printf("%d\n",b); //0
    printf("%u\n",b); //0
​
    a : 
       -1 :
          1111 1111
    a >> 31 
        char --> int 
            00000000 00000000 00000000 11111111 >> 31
            00000000 00000000 00000000 00000000

赋值运算符 =

双目运算符 , 结合性从右到左
    x = y;
把表达式y的值,赋值给x(隐含了一个条件 x必须是一个可写的地址,具备左值,一般来说,X为一个可变的数据对象 ”变量“)
​
赋值表达式的左边(左操作数)必须为一个”可写的地址“  左值
​
5 = 5; error
2 + 3 = 5; error
int i = 5; 
i++ = 6; error
i = 6;
​
赋值表达式:是由赋值运算符连接起来的式子,赋值表达式
赋值表达式的值:就是你赋值后左边那个操作数的值
​
i = 5;
a = i = 5;
    ====>
a = (i = 5);
​
复合的赋值运算符 : 赋值运算符可以和算术运算符,位运算符复合的赋值运算符
 += -= *= /= %= >>= <<= != |= &= ^=
 a+=b ====> a = a + b;
 a >>= 2 ====> a = a >> 2;
​
 a = a+b ; ===> a+=b;

温馨提示: 如果说下面这个问题不是C新手最常见的问题,那么它至少也是令人恼火一个错误!!! 绝大部分其他的语言使用 = 操作符来进行比较 相等性 。在C语言中,你必须要用== 来进行比较,单个= 是赋值 这个的陷阱在于: 在测试相等性的时候出现赋值符号也是合法的!! 它不是一个语法错误 if(a==b) if(a=b) no error

条件运算符 ? :

三目运算符 结合性从右到左
experion ? a : b
上面这个是一个条件表达式
    如果experion的值是为真,则整个条件表达式的值就为a
    如果experion的值是为假,则整个条件表达式的值就为b
​
eg:
    if(a>b)
    {
        a = 250;
    }
    else
    {
        a = 520;
    }
     a = (a>b) ? 250 :   520
     a = (a>b) ? (a = 250) : (a = 520)

逗号表达式

双目运算符,优先级就是最低的,结合性从左到右
​
表达式1 ,表达式2 ,表达式3 ......
​
逗号表达式的求值顺序:先求表达式1的值,再求表达式2的值,再求表达式3的值
    整个逗号表达式的值就是表达式3的值
​
eg:
    int a = 5 , b =6;
    a = (a = 6 , a + b );
​
    逗号表达式的扩展形式:
        表达式1 , 表达式2 , 表达式3 ,.......,表达式n
        求值顺序:  
            先求1,2,3,4,5,最后整个逗号表达式的值,是不是就是表达式n的值 

指针运算符

 

sizeof()求字节运算符

sizeof(类型); 求出这个类型的字节数
sizeof(typeof(1));
sizeof(typeof(1.0));

分量运算符

求结构体的成员变量  .  ->
等后面结构体的专题再讲

下标运算符

int a[10];
a[0];
a[1];
a[2];
[]
.....
后面数组的时候也会涉及

强制类型转换的运算符

语法:(类型)值 eg: (int)3.5 ===>3 typeof((int)3.5) ===> int

其他运算符

如:
    函数调用符()
    int func(int a , int b)
    {
        //asdhuiasghduiasd;
    }
​
    int main()
    {
        func(10,29);
    }

总结

运算符的优先级和结合性

= 不同于 ==

由Algol派生而来的大多数程序设计语言,例如:Ada,使用:== 作为赋值运算符,但是符号 = 作为比较运算符,而我们的C使用了另外一种表示方法,符号 = 作为赋值,== 作为比较!
一般来说,赋值运算符肯定是比 比较运算符,出现次数更加多,因此字符较少的 = 作为了赋值运算符
    该语句的本意应该是检查x是否等于y
    if(x = y)
    {
        ...
        break;
    }
    实际上将 y赋值给了x

&和| 不同于 && 和 ||

运算符优先级

单目运算符>算术运算符>关系运算符>逻辑运算符>赋值运算符>逗号运算符
我们需要记住两句话:
    1、任何一个逻辑运算符的优先级低于任何一个关系运算符
    2、移位运算符的优先级要比算术运算符要低,但是要比关系运算符要高
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言运算符优先级是根据其不同的运算符来确定的。同一优先级的运算符,运算次序由结合方向所决定。一般来说,优先级从高到低排列如下:逻辑非(!) > 算术运算符 > 关系运算符 > 逻辑与(&&) > 逻辑或(||) > 赋值运算符。这意味着在表达式,拥有更高优先级的运算符会先进行计算,然后再计算优先级较低的运算符。这样可以确保表达式按照正确的顺序进行计算。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C语言运算符优先级.pdf](https://download.csdn.net/download/helloepl/12015321)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [【C语言基础】-运算符](https://blog.csdn.net/weixin_44247448/article/details/124077281)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [嵌入式系统的C语言项目代码示例,使用基本的GPIO控制和定时器功能](https://download.csdn.net/download/weixin_44609920/88223543)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值