从零开始学嵌入式技术之C语言06:运算符基础

        运算符是一种特殊的符号,用以用于数据的运算、赋值和比较等。

        表达式指的是一组运算数、运算符的组合,表达式一定具有值,一个变量或一个常量就是一个表达式,变量、常量与运算符也可以组成复杂一些的表达式。

一:运算符分类

(1)按照操作数个数分类:

  • 一元运算符(一目运算符)
  • 二元运算符(二目运算符)
  • 三元运算符(三目运算符)

(2) 按照功能分类:

  • 算术运算符
  • 赋值运算符
  • 关系运算符
  • 逻辑运算符
  • 位运算符

 二:算术运算符

        算术运算符是对数值类型的变量进行运算的,在C程序中使用的非常多。

运算符

描述

操作数个数

组成的表达式的值

副作用

+

正号

1

操作数本身

-

负号

1

操作数符号取反

+

加号

2

两个操作数之和

-

减号

2

两个操作数之差

*

乘号

2

两个操作数之积

/

除号

2

两个操作数之商

%

取模(取余)

2

两个操作数相除的余数

++

自增

1

操作数自增前或自增后的值

- -

自减

1

操作数自减前或自减后的值

//正号和负号
#include <stdio.h>

int main()
{
    int x = 12;
    int x1 = -x, x2 = +x;

    int y = -67;
    int y1 = -y, y2 = +y;

    printf("x1=%d, x2=%d \n", x1, x2);
    printf("y1=%d, y2=%d \n", y1, y2);

    return 0;
}
//加、减、乘、除
#include <stdio.h>

int main()
{
    int a = 5 + 2.5;
    printf("%d\n", a * a);

    double b = 6 / 4;
    printf("%f\n", b); // 输出 1.000000

    double c = 6.0 / 4;
    printf("%f\n", c); // 输出 1.500000

    return 0;
}

 注意:整数之间做除法时,结果只保留整数部分而舍弃小数部分。

//取模(取余)
#include <stdio.h>

int main()
{
    int res1 = 10 % 3;
    printf("%d\n", res1);

    int res2 = -10 % 3;
    printf("%d\n", res2);

    int res3 = 10 % -3;
    printf("%d\n", res3);

    int res4 = -10 % -3;
    printf("%d\n", res4);

    return 0;
}

 注意运算结果的符号与被模数也就是第一个操作数相同。

自增和自减

  1. 自增、自减运算符可以写在操作数的前面也可以写在操作数后面,不论前面还是后面,对操作数的副作用是一致的。 
  2. 自增、自减运算符在前在后,对于表达式的值是不同的。 如果运算符在前,表达式的值是操作数自增、自减之后的值;如果运算符在后,表达式的值是操作数自增、自减之前的值。
//自增和自减
#include <stdio.h>

int main()
{
    int i1 = 10, i2 = 20;
    int i = i1++;
    printf("%d\n", i);  // 10
    printf("%d\n", i1); // 11

    i = ++i1;
    printf("%d\n", i);  // 12
    printf("%d\n", i1); // 12

    i = i2--;
    printf("%d\n", i);  // 20
    printf("%d\n", i2); // 19

    i = --i2;
    printf("%d\n", i);  // 18
    printf("%d\n", i2); // 18

    return 0;
}

三:关系运算符(比较运算符)

运算符

描述

操作数个数

表达式的值

副作用

==

相等

2

0 或 1

!=

不等

2

0 或 1

<

小于

2

0 或 1

>

大于

2

0 或 1

<=

小于等于

2

0 或 1

>=

大于等于

2

0 或 1

#include <stdio.h>

int main() 
{
    int a = 8;
    int b = 7;

    printf("a>b的值:%d \n", a > b); 
    printf("a>=b的值:%d \n", a >= b); 
    printf("a<b的值:%d \n", a < b); 
    printf("a<=b的值:%d \n", a <= b);
    printf("a==b的值:%d \n", a == b);
    printf("a!=b的值:%d \n", a != b);

    return 0;;
}

 四:逻辑运算符

运算符

描述

操作数个数

表达式的值

副作用

&&

逻辑与

2

0 或 1

||

逻辑或

2

0 或 1

!

逻辑非

1

0 或 1

 (1):逻辑与 &&

        如果两个操作数都为真(非零),那么表达式的值为真,否则为假。

        如果第一个操作数为假,第二个操作数没有计算的必要了,这种现象称为短路现象。

#include <stdio.h>

int main()
{
    double score = 70; // 成绩

    if (score >= 60 && score <= 80)
    {
        printf("ok1 \n");
    }
    else
    {
        printf("ok2 \n");
    }

    int a = 10, b = 99;

    // 短路现象
    if (a < 2 && ++b > 99)
    {
        printf("ok100");
    }
    printf("b=%d\n", b);

    return 0;
}

(2):逻辑或 ||

        只要有一个操作数为真,表达式的值就为真;两个操作数都为假,表达式的值为假。

        如果第一个操作数为真,第二个操作数没有计算的必要了,这种现象称为短路现象。

#include <stdio.h>

int main()
{
    double score = 70;

    if (score >= 70 || score <= 80)
    {
        printf("ok1 \n");
    }
    else
    {
        printf("ok2 \n");
    }

    int a = 10, b = 99;

    // 短路现象
    if (a > 5 || b++ > 100)
    { //
        printf("ok100 \n");
    }
    printf("b=%d\n", b);

    return 0;
}

 (3):逻辑非

        操作数状态取反作为表达式的值。

#include <stdio.h>

int main()
{
    int score = 100;
    int res = score > 99;

    if (res)
    {
        printf("hello, tom \n");
    }
    if (!res)
    { 
        printf("hello,jack \n");
    }

    return 0;
}

五:赋值运算符

运算符

描述

操作数个数

表达式的值

副作用

=

赋值

2

左边操作数的值

+=

相加赋值

2

左边操作数的值

-=

相减赋值

2

左边操作数的值

*=

相乘赋值

2

左边操作数的值

/=

相除赋值

2

左边操作数的值

%=

取余赋值

2

左边操作数的值

<<=

左移赋值

2

左边操作数的值

>>=

右移赋值

2

左边操作数的值

&=

按位与赋值

2

左边操作数的值

^=

按位异或赋值

2

左边操作数的值

|=

按位或赋值

2

左边操作数的值

  1. 赋值运算符的第一个操作数(左值)必须是变量的形式,第二个操作数可以是任何形式的表达式。
  2. 赋值运算符的副作用针对第一个操作数。
#include <stdio.h>

int main()
{
    int a = 10, b = 20, c = 30;

    c += 3;   // 等价于 c = c + 3;   计算后c的值变为33
    c += b;   // 等价于 c = c + b;   计算后c的值变为53
    a += 1.7; // 等价于 a = a + 1.7  计算后a的值变为11

    printf("a=%d b=%d c=%d", a, b, c);

    return 0;
}

 六:位运算符

运算符

描述

操作数个数

副作用

&

按位与

2

|

按位或

2

^

按位异或

2

~

按位取反

1

<<

按位左移

2

>>

按位右移

2

注意:操作数进行位运算的时候,以它的补码形式进行运算。

(1):按位与、按位或、按位异或 

#include <stdio.h>

int main()
{
    int a = 17;
    int b = -12;

    printf("a&b=%d\n", a & b); // a&b=16
    printf("a|b=%d\n", a | b); // a|b=-11
    printf("a^b=%d\n", a ^ b); // a^b=-27

    return 0;
}

(2):按位取反

#include <stdio.h>

int main()
{
    int a = 17;
    int b = -12;

    // 按位非
    printf("~a=%d\n", ~a); 
    printf("~b=%d\n", ~b); 

    return 0;
}

(3):按位左移、按位右移

#include <stdio.h>

int main()
{
    int a = 17;
    int b = -12;

    // 按位左移
    printf("a<<2=%d\n", a << 2); // a<<2=68
    printf("b<<2=%d\n", b << 2); // b<<2=-48

    // 按位右移
    printf("a>>3=%d\n", a >> 3); // a>>3=2
    printf("b>>3=%d\n", b >> 3); // b>>3=-2

    return 0;
}

七:​​​​​​​三元运算符

基本语法:

        条件表达式? 表达式1: 表达式2;

        如果条件表达式为非0(真),整个表达式的值是表达式1;

        如果条件表达式为0(假),整个表达式的值是表达式2;

#include <stdio.h>

int main()
{
    int a = 10;
    int b = 99;
    int res = a > b ? a++ : b--;
    int n1 = a > b ? 1.1 : 1.2;

    printf("a=%d \n", a);
    printf("b=%d \n", b);
    printf("res=%d \n", res);

    return 0;
}
  1. 计算两个数的最大值a , b
#include <stdio.h>

int main()
{
    int a = 10;
    int b = 100;

    int max = a > b ? a : b;

    printf("a和b中最大的数字:%d", max);

    return 0;
}

 2.计算三个数的最大值

#include <stdio.h>

int main()
{
    int a = 10;
    int b = 100;
    int c = 199;

    // int max1 = a>b ? a : b;
    // int max2 = max1>c ? max1:c;
    int max = (a > b ? a : b) > c ? (a > b ? a : b) : c;

    printf("a、b、c中最大的数字:%d", max);

    return 0;
}

 八:​​​​​​​运算符优先级

优先级

运算符

名称或含义

结合方向

1

[]

数组下标

左到右

()

圆括号

.

成员选择(对象)

->

成员选择(指针)

2

-

负号运算符

右到左

(类型)

强制类型转换

++

自增运算符

--

自减运算符

*

取值运算符

&

取地址运算符

!

逻辑非运算符

~

按位取反运算符

sizeof

长度运算符

3

/

左到右

*

%

余数(取模)

4

+

左到右

-

5

<<

左移

左到右

>>

右移

6

>

大于

左到右

>=

大于等于

<

小于

<=

小于等于

7

==

等于

左到右

!=

不等于

8

&

按位与

左到右

9

^

按位异或

左到右

10

|

按位或

左到右

11

&&

逻辑与

左到右

12

||

逻辑或

左到右

13

?:

条件运算符

右到左

14

=

赋值运算符

右到左

/=

除后赋值

*=

乘后赋值

%=

取模后赋值

+=

加后赋值

-=

减后赋值

<<=

左移后赋值

>>=

右移后赋值

&=

按位与后赋值

^=

按位异或后赋值

|=

按位或后赋值

15

,

逗号运算符

左到右

总结:

  1. 不要过多的依赖运算的优先级来控制表达式的执行顺序,这样可读性太差,尽量使用小括号来控制表达式的执行顺序。
  2. 不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它分成几步来完成。
  3. 运算符优先级不用刻意地去记忆,总体上:一元运算符 > 算术运算符 > 关系运算符 > 逻辑运算符 > 三元运算符 > 赋值运算符。

        本章的内容就到这里。

        关注我一起成为嵌入式大佬。

 

  • 26
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值