Bootstrap

c语言——运算符

一.运算符的简介

1.运算符的定义:运算符就是在c语言中程序执行运算的逻辑符号。

优先级

运算符

名称或含义

使用形式

结合方向

说明

1

[]

数组下标

数组名[常量表达式]

左到右

--

()

圆括号

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

--

.

成员选择(对象)

对象.成员名

--

->

成员选择(指针)

对象指针->成员名

--

2

-

负号运算符

-表达式

右到左

单目运算符

~

按位取反运算符

~表达式

++

自增运算符

++变量名/变量名++

--

自减运算符

--变量名/变量名--

*

取值运算符

*指针变量

&

取地址运算符

&变量名

!

逻辑非运算符

!表达式

(类型)

强制类型转换

(数据类型)表达式

--

sizeof

长度运算符

sizeof(表达式)

--

3

/

表达式/表达式

左到右

双目运算符

*

表达式*表达式

%

余数(取模)

整型表达式%整型表达式

4

+

表达式+表达式

左到右

双目运算符

-

表达式-表达式

5

<< 

左移

变量<<表达式

左到右

双目运算符

>> 

右移

变量>>表达式

6

大于

表达式>表达式

左到右

双目运算符

>=

大于等于

表达式>=表达式

小于

表达式<表达式

<=

小于等于

表达式<=表达式

7

==

等于

表达式==表达式

左到右

双目运算符

!=

不等于

表达式!= 表达式

8

&

按位与

表达式&表达式

左到右

双目运算符

9

^

按位异或

表达式^表达式

左到右

双目运算符

10

|

按位或

表达式|表达式

左到右

双目运算符

11

&&

逻辑与

表达式&&表达式

左到右

双目运算符

12

||

逻辑或

表达式||表达式

左到右

双目运算符

13

?:

条件运算符

表达式1?

表达式2: 表达式3

右到左

三目运算符

14

=

赋值运算符

变量=表达式

右到左

--

/=

除后赋值

变量/=表达式

--

*=

乘后赋值

变量*=表达式

--

%=

取模后赋值

变量%=表达式

--

+=

加后赋值

变量+=表达式

--

-=

减后赋值

变量-=表达式

--

<<=

左移后赋值

变量<<=表达式

--

>>=

右移后赋值

变量>>=表达式

--

&=

按位与后赋值

变量&=表达式

--

^=

按位异或后赋值

变量^=表达式

--

|=

按位或后赋值

变量|=表达式

--

15

逗号运算符

表达式,表达式,…

左到右

--

二. 运算的分类

  • 按照功能划分:
    • 算术运算符
    • 赋值运算符
    • 关系运算符
    • 逻辑运算符
    • 位运算符
  • 按照参与运算的操作数个数划分:
    • 单目运算
      • 只有一个操作数 如 : i++;
    • 双目运算
      • 有两个操作数 如 : a + b;
    • 三目运算
      • C语言中唯一的一个,也称为问号表达式 如: a>b ? 1 : 0;

算数运算符

优先级名称符号说明
3乘法运算符*双目运算符,具有左结合性
3除法运算符/双目运算符,具有左结合性
3求余运算符 (模运算符)%双目运算符,具有左结合性
4加法运算符+双目运算符,具有左结合性
4减法运算符-双目运算符,具有左结合性

赋值运算符

优先级名称符号说明
14赋值运算符=双目运算符,具有右结合性
14除后赋值运算符/=双目运算符,具有右结合性
14乘后赋值运算符 (模运算符)*=双目运算符,具有右结合性
14取模后赋值运算符%=双目运算符,具有右结合性
14加后赋值运算符+=双目运算符,具有右结合性
14减后赋值运算符-=双目运算符,具有右结合性
#include <stdio.h>
int main(){
    // 简单的赋值运算符 =
    // 会将=右边的值赋值给左边
    int a = 10;
    printf("a = %i\n", a); // 10
}

#include <stdio.h>
int main(){
     // 复合赋值运算符 += -= *= /= %=
     // 将变量中的值取出之后进行对应的操作, 操作完毕之后再重新赋值给变量
     int num1 = 10;
     // num1 = num1 + 1; num1 = 10 + 1; num1 = 11;
     num1 += 1;
     printf("num1 = %i\n", num1); // 11
     int num2 = 10;
     // num2 = num2 - 1; num2 = 10 - 1; num2 = 9;
     num2 -= 1;
     printf("num2 = %i\n", num2); // 9
     int num3 = 10;
     // num3 = num3 * 2; num3 = 10 * 2; num3 = 20;
     num3 *= 2;
     printf("num3 = %i\n", num3); // 20
     int num4 = 10;
     // num4 = num4 / 2; num4 = 10 / 2; num4 = 5;
     num4 /= 2;
     printf("num4 = %i\n", num4); // 5
     int num5 = 10;
     // num5 = num5 % 3; num5 = 10 % 3; num5 = 1;
     num5 %= 3;
     printf("num5 = %i\n", num5); // 1
}


#include <stdio.h>
int main(){
    int number = 10;
    // 赋值运算符优先级是14, 普通运算符优先级是3和4, 所以先计算普通运算符
    // 普通运算符中乘法优先级是3, 加法是4, 所以先计算乘法
    // number += 1 + 25; number += 26; number = number + 26; number = 36;
    number += 1 + 5 * 5;
    printf("number = %i\n", number); // 36
}

自增自减运算符

优先级名称符号说明
2自增运算符(在后)i++单目运算符,具有左结合性
2自增运算符(在前)++i单目运算符,具有右结合性
2自减运算符(在后)i–单目运算符,具有左结合性
2自减运算符(在前)–i单目运算符,具有右结合性

sizeof运算符

  • sizeof可以用来计算一个变量或常量、数据类型所占的内存字节数

    • 标准格式: sizeof(常量 or 变量);
  • sizeof的几种形式

    • sizeof( 变量\常量 );
      • sizeof(10);
      • char c = 'a'; sizeof(c);
    • sizeof 变量\常量;
      • sizeof 10;
      • char c = 'a'; sizeof c;
    • sizeof( 数据类型);
      • sizeof(float);
      • 如果是数据类型不能省略括号
#include <stdio.h>
int main(){
    int a = 10;
    double b = 3.14;
    // 由于sizeof的优先级比+号高, 所以会先计算sizeof(a);
    // a是int类型, 所以占4个字节得到结果4
    // 然后再利用计算结果和b相加, 4 + 3.14 = 7.14
    double res = sizeof a+b;
    printf("res = %lf\n", res); // 7.14
}

数组长度的计算方法

  • 因为数组在内存中占用的字节数取决于其存储的数据类型和数据的个数
    • 数组所占用存储空间 = 一个元素所占用存储空间 * 元素个数(数组长度)
  • 所以计算数组长度可以使用如下方法
    数组的长度 = 数组占用的总字节数 / 数组元素占用的字节数
    int ages[4] = {19, 22, 33, 13};
    int length =  sizeof(ages)/sizeof(int);
    printf("length = %d", length);
输出结果: 4

逗号运算符

  • 在C语言中逗号“,”也是一种运算符,称为逗号运算符。 其功能是把多个表达式连接起来组成一个表达式,称为逗号表达式
  • 逗号运算符会从左至右依次取出每个表达式的值, 最后整个逗号表达式的值等于最后一个表达式的值
  • 格式: 表达式1,表达式2,… …,表达式n;
    • 例如: int result = a+1,b=3*4;
#include <stdio.h>
int main(){
    int a = 10, b = 20, c;
    // ()优先级高于逗号运算符和赋值运算符, 所以先计算()中的内容
    // c = (11, 21);
    // ()中是一个逗号表达式, 结果是最后一个表达式的值, 所以计算结果为21
    // 将逗号表达式的结果赋值给c, 所以c的结果是21
    c = (a + 1, b + 1);
    printf("c = %i\n", c); // 21
}

关系运算符

  • 关系运算符的运算结果只有2种:如果条件成立,结果就为1,也就是“真”;如果条件不成立,结果就为0,也就是“假”
优先级名称符号说明
6大于运算符>双目运算符,具有左结合性
6小于运算符<双目运算符,具有左结合性
6大于等于运算符>=双目运算符,具有左结合性
6小于等于运算符<=双目运算符,具有左结合性
7等于运算符==双目运算符,具有左结合性
7不等于运算符!=双目运算符,具有左结合性
#include <stdio.h>
int main(){
    int result = 10 > 5;
    printf("result = %i\n", result); // 1
    result = 5 < 10;
    printf("result = %i\n", result); // 1
    result = 5 > 10;
    printf("result = %i\n", result); // 0
    result = 10 >= 10;
    printf("result = %i\n", result); // 1
    result = 10 <= 10;
    printf("result = %i\n", result); // 1
    result = 10 == 10;
    printf("result = %i\n", result); // 1
    result = 10 != 9;
    printf("result = %i\n", result); // 1
}


#include <stdio.h>
int main(){
    // == 优先级 小于 >, 所以先计算>
    // result = 10 == 1; result = 0;
    int result = 10 == 5 > 3;
    printf("result = %i\n", result); // 0
}


#include <stdio.h>
int main(){
    // == 和 != 优先级一样, 所以按照结合性
    // 关系运算符是左结合性, 所以从左至右计算
    // result = 0 != 3; result = 1;
    int result = 10 == 5 != 3;
    printf("result = %i\n", result); // 1
}

逻辑运算符

优先级名称符号说明
2逻辑非运算符!单目运算符,具有右结合性
11逻辑与运算符&&双目运算符,具有左结合性
12逻辑或运算符\|\|双目运算符,具有左结合性
  • 逻辑非
    • 格式: ! 条件A;
    • 运算结果: 真变假,假变真
    • 运算过程:
      • 先判断条件A是否成立,如果添加A成立, 那么结果就为0,即“假”;
      • 如果条件A不成立,结果就为1,即“真”
    • 使用注意:
      • 可以多次连续使用逻辑非运算符
      • !!!0;相当于(!(!(!0)));最终结果为1
#include <stdio.h>
int main(){
    // ()优先级高, 先计算()里面的内容
    // 10==10为真, 所以result = !(1);
    // !代表真变假, 假变真,所以结果是假0
    int result = !(10 == 10);
    printf("result = %i\n", result); // 0
}
  • 逻辑与
    • 格式: 条件A && 条件B;
    • 运算结果:一假则假
    • 运算过程:
      • 总是先判断"条件A"是否成立
      • 如果"条件A"成立,接着再判断"条件B"是否成立, 如果"条件B"也成立,结果就为1,即“真”
      • 如果"条件A"成立,"条件B"不成立,结果就为0,即“假”
      • 如果"条件A"不成立,不会再去判断"条件B"是否成立, 因为逻辑与只要一个不为真结果都不为真
    • 使用注意:
      • "条件A"为假, "条件B"不会被执行
#include <stdio.h>
int main(){
    //               真     &&    真
    int result = (10 == 10) && (5 != 1);
    printf("result = %i\n", result); // 1
    //          假     &&    真
    result = (10 == 9) && (5 != 1);
    printf("result = %i\n", result); // 0
    //          真     &&    假
    result = (10 == 10) && (5 != 5);
    printf("result = %i\n", result); // 0
    //          假     &&    假
    result = (10 == 9) && (5 != 5);
    printf("result = %i\n", result); // 0
}


#include <stdio.h>
int main(){
    int a = 10;
    int b = 20;
    // 逻辑与, 前面为假, 不会继续执行后面
    int result = (a == 9) && (++b);
    printf("result = %i\n", result); // 1
    printf("b = %i\n", b); // 20
}
  • 逻辑或
    • 格式: 条件A || 条件B;
    • 运算结果:一真则真
    • 运算过程:
      • 总是先判断"条件A"是否成立
      • 如果"条件A"不成立,接着再判断"条件B"是否成立, 如果"条件B"成立,结果就为1,即“真”
      • 如果"条件A"不成立,"条件B"也不成立成立, 结果就为0,即“假”
      • 如果"条件A"成立, 不会再去判断"条件B"是否成立, 因为逻辑或只要一个为真结果都为真
    • 使用注意:
      • "条件A"为真, "条件B"不会被执行
#include <stdio.h>
int main(){
    //               真     ||    真
    int result = (10 == 10) || (5 != 1);
    printf("result = %i\n", result); // 1
    //          假     ||    真
    result = (10 == 9) || (5 != 1);
    printf("result = %i\n", result); // 1
    //          真     ||    假
    result = (10 == 10) || (5 != 5);
    printf("result = %i\n", result); // 1
    //          假     ||    假
    result = (10 == 9) || (5 != 5);
    printf("result = %i\n", result); // 0
}


#include <stdio.h>
int main(){
    int a = 10;
    int b = 20;
    // 逻辑或, 前面为真, 不会继续执行后面
    int result = (a == 10) || (++b);
    printf("result = %i\n", result); // 1
    printf("b = %i\n", b); // 20
}

三目运算符

  • 三目运算符,它需要3个数据或表达式构成条件表达式

  • 格式: 表达式1?表达式2(结果A):表达式3(结果B)

    • 示例: 考试及格 ? 及格 : 不及格;
  • 求值规则:

    • 如果"表达式1"为真,三目运算符的运算结果为"表达式2"的值(结果A),否则为"表达式3"的值(结果B)
示例:
    int a = 10;
    int b = 20;
    int max = (a > b) ? a : b;
    printf("max = %d", max);
    输出结果: 20
等价于:
    int a = 10;
    int b = 20;
    int max = 0;
    if(a>b){
      max=a;
    }else {
       max=b;
    }
    printf("max = %d", max);
  • 注意点
    • 条件运算符的运算优先级低于关系运算符和算术运算符,但高于赋值符
    • 条件运算符?和:是一个整体,不能分开使用
#include <stdio.h>
int main(){
    int a = 10;
    int b = 5;
    // 先计算 a > b
    // 然后再根据计算结果判定返回a还是b
    // 相当于int max= (a>b) ? a : b;
    int max= a>b ? a : b;
    printf("max = %i\n", max); // 10
}


#include <stdio.h>
int main(){
    int a = 10;
    int b = 5;
    int c = 20;
    int d = 10;
    // 结合性是从右至左, 所以会先计算:后面的内容
    // int res = a>b?a:(c>d?c:d);
    // int res = a>b?a:(20>10?20:10);
    // int res = a>b?a:(20);
    // 然后再计算最终的结果
    // int res = 10>5?10:(20);
    // int res = 10;
    int res = a>b?a:c>d?c:d;
    printf("res = %i\n", res);
}
;