运算符与表达式

运算符与表达式

算术运算符

用于处理四则运算。

+

  • 正号/加

  • 负号/减

*

  • 乘法

/

  • 除法
  • 注意事项
    • 除法运算后,得到的结果赋值给整型变量时,只取整数部分
    • 除 0 是错误

%

  • 取余
    • 10 % 3 = 1
  • 注意事项
    • 对 0 取余是错误
      • 10 % 0
    • 不允许对小数取余
      • 35 % 3.14
    • 对负数取余,结果为余数的绝对值
      • 10 % -3 = 1

++

a = 2; b=++a; // a=3;b=3
a = 2; b=a++; // a=3;b=2
  • 前缀自增:先自增,再取值
  • 后缀自增:先取值,再自增

a = 2; b=--a; // a=1;b=1
a = 2; b=a--; // a=1;b=2
  • 前缀自减:先自减,再取值
  • 后缀自减:先取值,再自减

赋值运算符

用于将表达式的值赋给变量。

=

  • 赋值

+=

  • 加等

-=

  • 减等

*=

  • 乘等

/=

  • 除等

%=

  • 模等

示例

a=2;b=3;    // a=2;b=3;
a=0;a+=2;   // a=0+2
a=5;a-=3;   // a=5-3

比较运算符

用于表达式的比较,并返回一个真值或假值。

  • 判等

!=

  • 不等于

<

  • 小于

  • 大于

>=

  • 大于等于

逻辑运算符

用于根据表达式的值返回真值或假值。

&&

  • 逻辑与

||

  • 逻辑或

!

  • 逻辑非 (0 为假,非 0 为真)

类型转换

转换原则

  • 示意图
    运算符与表达式
  • 占用内存字节数少的类型,向占用内存字节数多的类型转换,以保证精度不降低

分类

  • 隐式转换
    • 由编译器自动完成
    • 由赋值产生的类型转换
      • 小转大,没问题
      • 大转小,有可能数据丢失
  • 强制转换

    大多数用于函数调用期间,实参给形参传值。

    • 语法
      (目标类型)待转换变量
      (目标类型)待转换表达式
      
    • 示例
      #define _CRT_SECURE_NO_WARNING
      #include 
      #include 
      
      int main(void)
      {
          float price = 3.6;
          int weight = 4;
      
          double sum1 = (int)price * weight;
          double sum2 = (int)(price * weight);
      
          printf("sum1 = %lf\n", sum1);  //sum1 = 12.000000
          printf("sum2 = %lf\n", sum2);  //sum2 = 14.000000
      
          system("pause");
          return 0;
      }
      

运算符优先级

示意图:运算符总结

运算符与表达式

++/– 优先级

  • 后缀优先级高于前缀

三目运算符 (?:)

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

    如果表达式 1 为真,取值表达式 2;否则,取值表达式 3 (类似于数据库中的 coalesce)。

  • 结合方向:从右向左

  • 加上小括号更具可读性

    “`c
    int m = a > b ? 69 : (a <b> 1,1 -> 0

    <pre><code>“`c
    ~(10011010)
    = 01100101
    “`

    • 性质
      • -a = ~a + 1
      • 取反的另一种写法:a ^ (~0) = ~a
  • 按位与 (&)
    • 全 1 为 1
      (10010011) & 
      (00111101) =
      (00010001)
      
    • 性质
      • n & (n -1) 的结果会消除二进制最低位的 1
      • n & (n – 1) = 0 说明这个数二进制位中只有 1 个 1
    • 应用
      • 判断奇偶
        • 奇数 & 1 1;偶数 & 1 0
        • a & 1 等价于 a % 2
      • 判断一个数是否是 2^n,如果 m & (m-1) 0,说明 m 是 2 的 n 次方

  • 按位或 (|)

    • 全假为假
      (10010011) |
      (00111101) =
      (10111111)
      
    • 应用
      • 可以将数字中指定的位置变为 1

      • 和 1 做位异或,会把最后一位变为 1

        (00 000 001) |
        (10 001 000) =
        (10 001 001)
        
  • 按位异或 (^)
    • 相同为假,不同为真 (无进位相加)
      (10010011) ^
      (00111101) =
      (10101110)
      
    • 异或运算的性质
      • n ^ 0 n (置换常用); n ^ n 0 (去重常用)

      • 满足交换律和结合律

        • 交换律:两个数交换位置,和/积不变

          “`c++
          a ^ b == b ^ a;
          “`

        • 结合律:三个数相加或相乘,其中任意两个数先加/乘,结果不变

          “`c++
          a ^ b ^ c == a ^ (b ^ c) == a ^ c ^ b
          “`

      • 自反性:a ^ b ^ b a ^ 0 a

        • 应用:不用额外变量交换两个数
    • 应用
      • 交换两个整数
        • 扩展:交换数据的三种方法

          “`c++
          // 按位异或 ^ -> 可以用来交换数据
          void test03()
          {
          int num1 = 10, num2 = 5;
          // 10 的二进制: 1010
          // 5 的二进制: 0101

          <pre><code>//int temp;
          //temp = num1;
          //num1 = num2;
          //num2 = temp;
          //printf("第1种方法:num1 = %d, num2 = %d\n", num1, num2);

          //int sum = num1 + num2;
          //num2 = sum – num2;
          //num1 = sum – num1;
          //printf("第2种方法:num1 = %d, num2 = %d\n", num1, num2);

          num1 = num1 ^ num2; // 1111
          num2 = num1 ^ num2; // 1010
          num1 = num1 ^ num2; // 0101
          printf("第3种方法:num1 = %d, num2 = %d\n", num1, num2);
          </code></pre>

          }

          “`

          • 三杯水法
          • 异或运算法
          • 求和法
      • 加密解密
        • 与一个 key 异或一次得到加密,再异或一次得到解密
      • 比较两个值是否相等
        • a ^ b 0 则相等
  • 位逻辑运算符与等号结合
    • 位与运算符 &=
      • val &= 0377 等价于 val = val & 0377
    • 位或运算符 |=
      • val |= 0377 相当于 val = val | 0377
    • 位异或运算符 ^=
      • val ^= 0377 相当于 val = val ^ 0377
  • 示例
    #define _CRT_SECURE_NO_WARNINGS
    #include 
    #include 
    #include 
    
    // 按位取反 ~
    void test01()
    {
        int num = 2;
        // 00 000 010 <- 2 的源码
        // 11 111 101 <- ~ 取反,计算机以补码形式表示,这个数就是计算结果的补码
        // 11 111 100 <- 补码 -1 = 计算结果的反码
        // 10 000 011 <- 计算结果的源码,首位表示负号,所以就是 -3
        // -3 <- 转为十进制
        printf("%d\n", ~num);  // -3
    }
    
    // 按位与 &
    void test02()
    {
        int num = 123;
        if ((num & 1) == 1)
            printf("num 是奇数\n");  // num 是奇数
        else
            printf("num 是偶数\n");
    }
    

移位运算符

  • 左移 <<
    • 每位左移 X 位,表示乘 2^X

    • 移位填充

      “`c
      (10001010)

    • 右移 X 位,表示除以 2^X

    • 移位填充

      (10001010) >> 2
      (0010010)
      
      • 如果是无符号的值,都是用 0 填充
      • 对于有符号的值,在不同的操作系统上,左边填充位不同,有的填 0,有的填充 1;默认填充 0
    • 应用
      • 求平均值 (右移 1 位,相当于除 2,并向下取整)
        4 + (10-4) >> 1 = (10+4) / 2 = 7
        
  • 示例
    // 移位运算符
    void test04()
    {
        int num = 2;
        // 2 转为二进制: 00 000 010
        // 左移2位: 00 001 000
        // 转为源码: 00 001 000
        // 转为十进制: 8
        printf("num << 2 = %d\n", num << 2);  // num <> 1 = %d\n", num >> 1);  // num >> 1 = 4
    }
    

sizeof 运算符

用于求字节数长度。

英仔
版权声明:本站原创文章,由 英仔 2022-08-05发表,共计2767字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)