3.运算符/表达式/程序执行结构

4 阅读5分钟

运算符/表达式/程序执行结构

运算符/表达式

表达式与语句

  • 区别
    • 表达式结尾无分号,语句结尾有分号

运算符

  • 算数运算法
    +
    - 
    * 
    / 
    %
    

整数相除结果会是整数,想要得到一个浮点型,可以再最前面*1.0进行类型转换,原因:运算寄存器默认是整数

  • 关系运算符

    >
    <
    ==
    >=
    <= 
    !=
    
    • 代码
      #include <stdio.h>
      
      int main()
      {
          int a = 10;
          int b = 20;
          printf("a > b = %d\n", a > b);
          return 0;
      }
      
  • 逻辑运算符

    • 与/and: &&
      • 两个条件必须为真
    • 或/or: ||
      • 两个条件一个为真
    • 非not: !
      • 结果取反
    #include <stdio.h>
    
    int main()
    {
        int a = 10;
        int b = 20;
        printf("(a<b)||(a==b): %d\n", (a<b)||(a==b));
        printf("(a<b)&&(a==b): %d\n", (a<b)&&(a==b));
        printf("!((a<b)&&(a==b)): %d\n", !((a<b)&&(a==b)));
    
        return 0;
    }
    

    逻辑运算符是懒惰运算,如果已知表达式结果,就不会继续往下运行了

  • 位运算符

    • 按位取反:~
      • 是按照比特位进行取反:
      char c1 = 2; // 0000 0010
      /*
         ~0000 0010
         -------------
          1111 1101  
      */ 
      
    • 按位与:&
      • 相同位置值都为1,则结果是1,否则结果是0
      char c1 = 2; // 0000 0010
      char c2 = 6; // 0000 0110
      c1 & c2 = 2;
      /*
          0000 0010
         &0000 0110
         --------------
          0000 0010  // 2
      /*
      
    • 按位或:|
      • bit位只要有一个是1,则结果是1,否则结果是0
      char c1 = 2; // 0000 0010
      char c2 = 6; // 0000 0110
      /*
          0000 0010
        | 0000 0110
        ---------------
          0000 0110
      */
      
    • 按位异或:^
      • 对所有bit位值相同则为0,不同则为1
      char c1 = 2; // 0000 0010
      char c2 = 6; // 0000 0110
      /*
          0000 0010
         ^0000 0110
         -------------
          0000 0100  // 4
      */
      
    • 按位左移:<<
      • 将数据向左边移动比特位,空白的数据补0
      char c1 = 2; // 0000 0010
      c1 << 2;
      /*
          0000 0010
          << 2
          -------------------
          0000 1000  // 8
       */
      
    • 按位右移:>>
      • 将数据向右边移动比特位,空白的数据补0
      char c2 = 6; // 0000 0110
      c2 >> 2;
      /**
          0000 0110
          >> 2
          ----------------
          0000 0001  // 1
       */
      

      按位右移根据编译器会有两种情况:算术右移空白位补符号位,逻辑右移空白位补0。具体需要试试

    • 代码:
      #include <stdio.h>
      
      int main()
      {
          char c1 = 2;
          char c2 = 6;
          printf("~c1: %d\n", ~c1);
          printf("c1 & c2: %d\n", c1 & c2);
          printf("c1 | c2: %d\n", c1 | c2);
          printf("c1 ^ c2: %d\n", c1 ^ c2);
          printf("c1 << 2: %d\n", c1 << 2);
          printf("c2 >> 2: %d\n", c2 >> 2);
          printf("c1: %d, c2: %d\n", c1, c2);
      
          return 0;
      }
      
  • 赋值运算符

    // 赋值语句:结尾分号,无值
    int i = 10;
    
    // 赋值表达式:没有结尾分号,有值,值为左边变量值
    i = 11
    
    • 复合赋值运算符:
      +=: 
      i += 5;  等价于  i = i + 5
      
      -= 
      *=
      /=
      %=
      
    • 代码:
    #include <stdio.h>
    
    int main()
    {
        int i = 10;
        i += 5;
        printf("i:%d\n", i);
        printf("i + 5: %d\n", i+5);
        printf("i:%d\n", i);
        return 0;
    }
    
  • 条件运算符

    • 三目运算符:
      语法格式:
      表达式1?表达式2:表达式3
      
      表达式1为真,返回表达式2
      表达式1为假,返回表达式3
      
      int i = 6;
      int i2 = (i>5?5:0);  // i2为5
      
    • 代码:
    #include <stdio.h>
    
    int main()
    {
        int j = 0;
        int j2 = (j>0?(j-=1):(j+=1));
        printf("j:%d, j2:%d\n", j, j2);
    
        return 0;
    }
    
  • 逗号运算符

    // 语法格式:
    表达式1,表达式2,表达式3
    结果是最后一个表达式的值
    
    printf("%d\n", (5+2, 5>0, 0));  // 结果是0
    
  • 指针运算符

    • 取地址符:&
    • 解地址符:*
  • 自增、自减运算符

    • 自增:

      • i++: 返回值是加后的值
      • ++i: 返回值是加前的值
    • 自减:i--

      • i--: 返回值是减后的值
      • --i: 返回值是减前的值
    • 代码:

    #include <stdio.h>
    
    int main()
    {
        int d1 = 5;
        int d2 = 5;
        printf("%d, %d\n", (d1++)+1, (++d2)+1);  // 6, 7
        printf("d1:%d, d2:%d\n", d1, d2);  // d1:6, d2:6
    
        return 0;
    }
    
  • 其他运算符

    • 下标运算符 [], 用于引用数组对应下标的成员
      int array[10];
      array[0]
      
    • 强制类型转换符:()
      int i = 5;
      long l = (long)i;
      
    • 求类型运算符typeof():用于求指定变量、数据的类型
    • 求类型运算符:typeof(): 返回的是数据类型

运算符优先级:弹幕运算符>算数运算符>关系运算符>逻辑运算符>条件运算符>赋值运算符

程序执行结构

  • 顺序结构
  • 分支结构
    • if语句
      if(表达式)
      {
          复合语句;
      }
      else if(表达式) 
      {
          复合语句B;
      } 
      else 
      {
          复合语句C;
      }
      
    • switch语句
      switch(表达式)
      {
          case 常量表达1:
              复合语句1;
              break;
          case 常量表达式2:
              复合语句2;
              break;
          ...
          default:
              复合语句;
              break;
      }
      
      • 没有break的话,一旦执行就会一直执行,直到碰到下一个break
      • 在本个switch里的每个case值必须是唯一的
  • 循环结构
    • for循环
      for(表达式1;表达式2;表达式3)
      {
          代码块;
      }
      

      执行过程:首次进入for,先运行表达式1,再判断表达式2是否成立,再执行代码块,再执行表达式3 接下来循环(不再执行表达式1):判断表达式2结构是否成立,执行代码块,执行表达式3

      • for(;;) 死循环
    • while循环
      while(表达式)
      {
          代码块;
      }
      

      执行过程:只要表达式为真,就一直执行。可以在里面配合if写break跳出循环

    • do...while循环
      do 
      {
          代码块;
      } while(表达式)
      
      • 先执行,再判断。至少会执行一次
    • goto配合if形成循环
      标签标识符:
          代码块;
          if(表达式) {
              goto 标签标识符;
          }
      
      • goto不能再函数之间跳转
      • goto不能定义变量
  • 循环控制语句
    • break 跳出循环
    • continue 继续下一次循环(不能作用于goto、switch)