C语言 | chap03 运算符

C语言中的运算符

  • 表达式:有一个或者多个操作数(变量\常量\字面值)与运算符组成

  • 表达式的值:根据运算符运算规则,表达式最终的结果

  • C语言中的运算符种类:

    • 算数运算符:+(加) , -(减) , *(乘) , /(除) , %(取余、模运算) , ++(自增) , --(自减)

    • 关系运算符:<(小于)、>(大于)、<=(小于等于)、>=(大于等于)、==(等于、判等)、!=(不等于)

    • 逻辑运算符:&& (与)、||(或) 、!(非)

    • 赋值运算符:

      • 简单赋值运算符: = (简单赋值)

      • 复合赋值运算符:

        • 算术复合赋值运算符:+=、-=、*=、/=、%=
        • 位运算复合赋值运算符:&=、|=、^=、<<=、>>=
    • 位运算符:&(位与)、|(位或)、~(位非)、^(位异或)、<<(位左移)、>>(位右移)

    • 条件运算符:?:(条件运算符、三元运算符、三目运算符)

    • 逗号运算符: ,

    • 指针运算符:&(取地址符)、*(寻址符、解引用符)

    • 求字节运算符:sizeof

    • 结构体运算符: . (结构体变量访问成员运算符) , -> (结构体指针)

    • 特殊运算符: () (更改优先级运算符) , [] (下标运算符) , {} (列表运算符)

  • 学习运算符主要学习什么?

    • 运算规则
    • 优先级
    • 结合性
    • 操作数个数

一 、算数运算符

1.1 + , - , * , / , %

  • 都是二元运算符(二元:两个操作数)

  • 运算规则: 与数学中基本一致

  • 特别注意的地方: 没有特别区分浮点除法和整数除法

    • C语言中算数运算符的结果类型由左右操作数类型决定.

      • 例如: 左右擦作数类型都为int时,结果为int (整除,不会四舍五入) ;

      • 左右操作数为double时,结果为double(浮点数除法, );

      • 一边为int ,一边为double ,结果是double (结果会为范围大的的类型);

        • 小技巧:若要使整数除法转换成浮点数除法 可以把一边变成double, 先用1.0乘以前面一个数 或者类型转换 (double) a / b ; (注意区分前后顺序)
      • 代码:

        int a = 10, b = 3;
        double c = a / b;
        printf("%.2lf\n", c); // 3.00
        c = 1.0 * a / b;
        printf("%.2lf\n", c); //3.33
        c = (double)a / b; // 类型转换
        printf("%.2lf\n", c); // 3.33
        c = double(a / b);
        printf("%.2lf\n", c); // 3.00
        
    • / 和 % 要求右操作数不能为0

    • % 取余运算符 :

      • 要求左右操作数必须为整数
      • py 往负无穷取 , C语言往0取;且C语言取余符号由被取余数决定,按正常运算进行取余,符号由左操作数决定
      • 代码:
        printf("%d\n", 5 % 3); // 2
        printf("%d\n", -5 % 3); // -2
        printf("%d\n", 5 % -3); // 2
        printf("%d\n", -5 % -3); // -2
        
    • 取余运算常用在:

      • 缩小数据范围
      • 判断整除 a%b == 0;

1.2 ++ 、 –

  • ++ 称之为自增运算符、–称之为自减运算符、都属于一元运算符

  • 以++为例:(–与++操作规则相同)

    • 前自增(前++):++操作数

      • 先对操作数进行自加一操作,然后取操作数的值
    • 后自增(后++):操作数++

      • 先取操作数的值,后对操作数进行自加1的操作
  • 注意

    • printf("%d",a++);就是打印出来a++之前的值
      • 因为a先取值,再执行++
    • a++;
      • printf("%d",a); 打印出来的就是a++之后的值
      • 因为a++,先取值再++已经执行完毕了
  • 在实际开发中,如果在一个表达式中使用了自增或自减运算符,则其操作数不要在表达式中出现多次。

    • eg:

      int i=0;
      printf(“%d\n”, ++i); //1
      printf(“%d\n”, i);//1
      int i=0;
      printf(“%d\n”, i++);//0
      printf(“%d\n”, i);//1
      int i=0;
      printf(“%d\n”, ++i);
      printf(“%d\n”, i++);
      printf(“%d\n”, --i);
      printf(“%d\n”, i--);
      printf(“%d\n”, i);
       
      I = 0;
      printf(“%d\n”, ++i + ++i + i);
      //会先把所有对i的操作 处理完 最后使用最后一个操作完的i值进行符号运算
       
      I = 0;
      printf(“%d\n”, ++i + --i + i-- + i++  + i);
      

二、关系运算符

  • == 、 != 、> 、<、 >=、<=

  • 关系运算符都是二元运算符,结合性都是从左到右

  • >、<、>=、<=的优先级都高于 == 、!=

  • 关系运算符的结果只有0和1,0表示不成立(false),1表示成立(true)

  • 代码:int a = 5;

    printf("%d\n",a>=1); //1
    printf("%d\n",a>10); //0
    printf("%d\n",1< a< 3); //1  
    // 1< a <3这种写法py是支持的,但是C语言不支持
    //C语言中上面表达式的结果恒定为1
    

三、逻辑运算

  • &&(逻辑与)、 ||(逻辑或)、!(逻辑非)

  • 从结果上说,1表示真,0表示假

  • 从操作数上说,非0表示真,0表示假

  • &&和||从结合性上来说都是从左到右的

  • &&的优先级高于||

  • 代码: a && b || c && d

    int a ;
    scanf("%d\n",&a);
    if (a % 2 ==1)
    {};
    if (a % 2 )
    {};
    // a % 2 ==1和 a % 2 结果一样
     
    例:// a == 0 a的值为0
    // a != 0 a的值则为1  (非0则为1)
    a = !!a 
     
    int a = 1 , b = 0;
    printf("%d\n" , b++ && a++); //逻辑与运算左侧出现0,则最终结果为0,后面不会再执行,叫做逻辑短路问题,a++不再执行
    printf("%d\n", a); // 1
    printf("%d\n", b); // 1
    
  • 逻辑短路问题:

    • 逻辑与的短路问题:

      • 当左操作数为假的时候,右操作数不执行
    • 逻辑或的短路问题:

      • 当左操作数为真的时候,右操作数不执行
    • 代码:

      int a = 1, b = 0;
      printf("%d\n", a && b); // 0
      printf("%d\n", a || b); // 1
      printf("%d\n", !a || b); // 0
      printf("%d\n", b++ && a++); // 0
      printf("%d\n", a); // 1
      printf("%d\n", b); // 1
      a = 1;
      b = 0;
      printf("%d\n", ++b || ++a); // 1
      printf("%d\n", a); // 1
      printf("%d\n", b); // 1
      

四、条件运算符

  • ?::条件运算符、三元运算符、三目运算符

  • 唯一的一个三个操作数的运算符

  • 操作数1 ? 操作数2 : 操作数3

    • 表示根据操作数1的真假,如果结果为真,操作数2执行并作为表达式结果;如果结果为假,则操作数3执行,并作为表达式结果

    • 代码:

      int a ;
      scanf("%d" , &a);
      a%2 == 0 ? printf("偶数\n") : printf("奇数\n");
      printf(a%2 == 0 ? printf("偶数\n") : printf("奇数\n"); //与上面结果一样
      

五、位运算符

  • 位运算符就是直接操作内存二进制的运算符

  • 常见的:&(位与)、|(位或)、~(位非)、^(位异或)、<<(位左移)、>>(位右移)

  • 运算符的含义:

    • &:二元运算符,将左右操作数内存直接按位进行与运算

      • 代码:

        short a = 18,b = 9;
        short c = a & b;
        //a : 0000 0000 0001 0010
        //b : 0000 0000 0000 1001
        //c : 0000 0000 0000 0000
        printf("hd \n", c ); // c = 0
        c = 17 & 13;
        printf("hd \n", c ); //1
        
    • |:二元运算符,左右操作数内存按位进行或操作

      • 代码:

        short a = 18,b = 9;
        short c = a | b;
        //a : 0000 0000 0001 0010
        //b : 0000 0000 0000 1001
        //c : 0000 0000 0001 1011
        printf("hd \n", c ); // c = 27
        c = 17 | 13;
        printf("hd \n", c ); //29
        
    • ~:一元运算符,将操作数内存按位取反

      • 代码

        short a = 2;
        short c = ~a;
        //a : 0 000 0000 0000 0010
        //~a : 1 111 1111 1111 1101
        printf("%hd\n",c); //-3
        c = ~b;
        // 0000 0000 0000 0000
        // 1111 1111 1111 1111(补码)
        // 1111 1111 1111 1110(反码)
        // 1000 0000 0000 0001(原码)
        printf("%hd\n",c);
         
         
         
        unsigned short a = 2, b = 0;
        unsigned short c = ~a;
        // 1111 1111 1111 1101
        // 1111 1111 1111 1111   2^16-1
        printf("%hu\n", c); // 2^16-3
        c = ~b;
        printf("%hu\n",c); // 2^16-1
        
    • ^:位异或,二元运算符,左右操作数内存按位进行异或运算

      • 相应位相同为0,不同为1

      • 代码:

        short a = 17, b = 9;
        short c = a ^ b;
        // a: 0000 0000 0001 0001
        // b: 0000 0000 0000 1001
        // c: 0000 0000 0001 1000
        printf("%hd\n", c); //24
         
         
        short a = 17, b = 9;
        a = a ^ b; // a' = a ^ b;
        b = a ^ b; // b' = a' ^ b = a ^ b ^ b;
        a = a ^ b; // a'' = a' ^ b' = a ^ b ^ a;
        printf("a = %hd\n", a);// a = 9
        printf("b = %hd\n", b);// b = 17
        //规律:
        // [0] ^ 1 -> 1 ^ 1 -> [0]
        // [0] ^ 0 -> 0 ^ 0 -> [0]
        // [1] ^ 1 -> 0 ^ 1 -> [1]
        // [1] ^ 0 -> 1 ^ 0 -> [1]
         
        //写法2:
        a ^= b ^= a ^= b ; 
        
    • 位移运算符:

      • 位移:将操作数内存中每一位向特定方向(向左、向右)移动指定位数。

      • 位移运算通常操作数为无符号整型

        • << :位左移运算符

          • 操作数1 << 操作数2 :将操作数1内存每一位往左移动操作数2位
          • 高位移出舍弃,低位补零
          • 往右移动n位相当于乘以2的n次
        • >>:位右移运算符

          • 操作数1 >> 操作数2 :将操作数1内存每一位往右移动操作数2位
          • 高位移出舍弃,低位补零
          • 往右移动n位相当于除以2的n次
        • 代码:

        int a = 16;
        printf("%d\n",a << 1); //32
        printf("%d\n",a << 2); //64
        printf("%d\n",a << 3); //128
        printf("%d\n",a << 4); //256
        printf("%d\n",a << 5); //512
        int a = 316;
        printf("%d\n",a >> 1); //158
        printf("%d\n",a >> 1); //79
        printf("%d\n",a >> 1); //39
        printf("%d\n",a >> 1); //19
         
         
        int a = 10 , b = 15;
        int c = (a + b) >> 1; //加和除以2
         
        
        • 代码例子:
        int a = 11;
        //1011
        //打印a二进制的低四位,不能直接打印1011
        //1:右移用最后一位进行取余,b = a % 2;
        //2: & 1 或者 | 0
        

六、赋值运算符

  • 简单赋值运算符

    • = :二元运算符,结合性从右到左,将右操作数的值赋给左操作数,要求左操作数必须为可被修改的变量

    • 赋值运算符优先级倒数第二低 (逗号为最低)

    • 代码

      int a , b , c ; a = b = c = 10;
      
  • 复合赋值运算符 (简写形式)

    • 算术复合赋值运算符:+=、-=、*=、/=、%= (简化代码)
    • 位运算复合赋值运算符:&=、|=、^=、<<=、>>=
    • eg: a += b -> a = a+b

七、逗号运算符

  • ,:逗号运算符

  • 一般形式:操作数1,操作数2 :先执行操作数1,在执行操作数2,然后将操作数2作为整个逗号表达式的结果

  • 优先级最低,二元运算符,结合性从左到右。

  • 例子:

    • 代码:

      int num;
      num = 100 , 200; //赋值的=要比逗号,优先级高
      printf("%d\n",num); //100
      printf("%d\n",(num = 100 , 200)); // 200 ,先执行赋值,再执行逗号,所以是200
      num = (1,2,3,4,5,6) 
      printf("%d\n",num); // 6
       
      int num = 13;
      num += num -=num *= num /= num //结合性从右到左 ,复合运算符
      printf("%d\n",num) // 0
       
      

八、C语言中的类型转换

  • C语言中的类型转换共分为2类:显示类型转换,隐式类型转换

  • 显示类型转换(强制类型转换)

    • (希望转换成的类型)操作数:将操作数转换成括号中的类型 (根据程序员的操作意识)

      • (double)10/3 (double)(10/3) // 转换符的优先级很高,需要用小括号来改变优先级
  • 隐式类型转换

    • 并不是程序员的主动行为,而是计算机自动完成的类型转换

    • 通常出现在不同类型操作数进行运算时

    • C语言要求进行运算时左右操作数类型一定要一致

      • 例子:
        			10.0   / 3
        			double  int
        					 | (隐式类型转换)
        				   double
        
  • 不同类型进行运算时,数据范围较小的类型会自动提升到范围较大的类型

    char , short   ——>会被提升至 int (默认)——>提升至 long ——> long long ——> 自定义数据类型
    float ——> double(默认)——> long double
     
    short  & float ——> int & double ——> (小范围提升至大范围)double & double ——> 结果为double
    
  • 隐式类型转换的陷阱:

    • unsigned int <-> int :int 转换为 unsigned int ,把int的符号位一起当作数据位一起读取
      -1 int ——> unsigned int 2^32-1
    • 代码:
      unsigned int size = 10; 
      if (size > -1)
       { 
      printf("AA\n"); 
      } 
      else { printf("BB\n"); 
      }
      

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黑眼圈子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值