zoukankan      html  css  js  c++  java
  • C 语言-运算符(算术运算符,类型转换,赋值运算符,自增,自减,sizeof 运算符,逗号运算符,关系运算符,逻辑运算符,三目运算符)

    目录

    运算符划分

    • 按照功能划分:

      • 算术运算符
      • 关系运算符
      • 逻辑运算符
      • 按位运算符
    • 按照参与运算的操作个数进行划分

      • 单目运算符

        • 只有一个操作数 如:i++
      • 双目运算符

        • 有两个操作数 如:a+b
      • 三目运算符

        • 有三个操作数 如:a > b ? 1:0 如果a>b时,a = 1,如果a<b时,a = 0

    运算符的优先级表

    • 运算符的优先级分为15级别,1级最高,15级最低

    • 在表达式中优先级高的优先于优先级低的先运算

    • 在一个运算量两侧的,优先级一样时按照运算符的结合性所规定的方向进行运算

      优先级运算符名称或含义使用形式结合方向说明
      1 [] 数组下标 数组名[常量表达式] 左到右  
        () 圆括号 (表达式)/函数名(形参表)    
        . 成员选择(对象) 对象.成员名    
        -> 成员选择(指针) 对象指针->成员名    
      2 - 负号运算符 -表达式 右到左 单目运算符
        (类型) 强制类型转换 (数据类型)表达式    
        ++ 自增运算符 ++变量名/变量名++ 单目运算符  
        -- 自减运算符 --变量名/变量名-- 单目运算符  
        * 取值运算符 *指针变量 单目运算符  
        & 取地址运算符 &变量名 单目运算符  
        ! 逻辑非运算符 !表达式 单目运算符  
        ~ 按位取反运算符 ~表达式 单目运算符  
        sizeof 长度运算符 sizeof(表达式)    
      3 / 表达式/表达式 左到右 双目运算符
        * 表达式*表达式 双目运算符  
        % 余数(取模) 整型表达式/整型表达式 双目运算符  
      4 + 表达式+表达式 左到右 双目运算符
        - 表达式-表达式 双目运算符  
      5 << 左移 变量<<表达式 左到右 双目运算符
        >> 右移 变量>>表达式 双目运算符  
      6 > 大于 表达式>表达式 左到右 双目运算符
        >= 大于等于 表达式>=表达式 双目运算符  
        < 小于 表达式<表达式 双目运算符  
        <= 小于等于 表达式<=表达式 双目运算符  
      7 == 等于 表达式==表达式 左到右 双目运算符
        != 不等于 表达式!= 表达式 双目运算符  
      8 & 按位与 表达式&表达式 左到右 双目运算符
      9 ^ 按位异或 表达式^表达式 左到右 双目运算符
      10 | 按位或 表达式|表达式 左到右 双目运算符
      11 && 逻辑与 表达式&&表达式 左到右 双目运算符
      12 || 逻辑或 表达式||表达式 左到右 双目运算符
      13 ?: 条件运算符 表达式1? 表达式2: 表达式3 右到左 三目运算符
      14 = 赋值运算符 变量=表达式 右到左  
        /= 除后赋值 变量/=表达式    
        *= 乘后赋值 变量*=表达式    
        %= 取模后赋值 变量%=表达式    
        += 加后赋值 变量+=表达式    
        -= 减后赋值 变量-=表达式    
        <<= 左移后赋值 变量<<=表达式    
        >>= 右移后赋值 变量>>=表达式    
        &= 按位与后赋值 变量&=表达式    
        ^= 按位异或后赋值 变量^=表达式    
        |= 按位或后赋值 变量|=表达式    
      15 , 逗号运算符 表达式,表达式,… 左到右 从左向右顺序运算
    • 虽然说运算符有很多,但是不用记住,使用小括号()扩起来就好了

    结合性简单介绍

    • c语言中有两种结合性,一种是左结合型,一种是右结合性
    • 左结合性--自左至右运算,右结合性--自右至左运算
    • 左结合性 例如:x + y -z,先计算x+y,计算后的结果再减z
    • 右结合性 例如:x = y = z, 将z的值赋值给y,再将y的值赋值给x

    算数运算符表

    运算符术语示例结果
    + 正号 +3 3
    - 负号 -3 -3
    + 10 + 5 15
    - 10 - 5 5
    * 10 * 5 50
    / 10 / 5 2
    % 取模(取余) 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;
    #include <stdio.h>
    
    int main(int argc, const char * argv[]) {
        /*
         +  加法
         -  减法
         *  乘法
         /  除法
         %  取模(取余)
         */
        int result;
        result = 1 + 1;
        printf("加法结果:result = %i
    ",result);
        result = 1 - 1;
        printf("减法结果:result = %i
    ",result);
        result = 2 * 3;
        printf("乘法结果:result = %i
    ",result);
        result = 10 / 2;
        printf("除法结果:result = %i
    ",result); // result = 5
        result = 10 % 3;
        printf("取模结果:result = %i
    ",result); // result = 1
      
        return 0;
    }

    取模运算符的注意点

    • 注意:取模运算只能对整数取模,不能对实数取模
        // 注意取模运算只能是整数取模不能是实数取模
        // result = 10.5 % 3; // 直接报错
    • 注意:取模运算的正负性,取决于左边的操作数
        // 取模运算的正负性,取决于左边的操作数
        result = 10 % -3;
        printf("取模正负性结果:result = %i
    ",result); // result = 1
        result = -10 % -3;
        printf("取模正负性结果:result = %i
    ",result); // result = -1
        result = -10 % 3;
        printf("取模正负性结果:result = %i
    ",result); // result = -1
        result = -0 % -3;
        printf("取模正负性结果:result = %i
    ",result); // result = 0
    • 注意:如果取模运算中,左边操作数小于右边操作数,那结果直接就是左边操作数,不会进行计算了
     // 如果取模运算中,左边操作数小于右边操作数,那结果直接就是左边操作数,不会进行计算了
        result = 10 % 100;
        printf("取模结果:result = %i
    ",result); // result = 10

    算术运算符的结合性

     // 算术运算符的结合性
        result = 3 + 4 + 5 + 6;
        printf("result的值是%i",result);

    算术运算符的优先级和结合性同时存在时

    • 先优先级,再按照结合性
     // 优先级+结合性
        result = 2 + 3 * 4 -4;
        printf("result的值是%i
    ",result); // 先计算乘法,再从左至右的结合性计算

    类型转换

    • 隐式转换
        // 系统自动进行的转换
        int number = 10.8;
        printf("number的值是%i
    ",number); // number = 10,
        // 大类型的转换成小类型的,系统会自动进行转换,由大类型转换为小类型,丢失精度
    • 显式转换
        // 显式转换-只需要在值前面加(类型)
        int value = (int)10.8;
        printf("value的值是%i
    ",value); // 10;
        // 大类型的转换成小类型的,系统会自动进行转换,由大类型转换为小类型,丢失精度
    • 在算术运算中,类型不一致时,系统会先将类型统一,统一成大类型进行计算
        // 在算术运算中,类型不一致时,系统会先将类型统一,统一成大类型进行计算
        int value2 = 10 + 9.9;
        // 10是int类型,9.9是double类型,int类型占4个字节,9.9占8个字节,所以先将int转为double类型
        // int value2 = 10.0 + 9.9
        // int value2 = 19.9
        // value2 是一个int类型,但是右边的19.9是double类型,这时候系统会做隐式转换,大类型转为小类型,既结果为19
        printf("value2的值是%i
    ",value2); // 19;
    • 算术运算符的注意点-参与运算的操作数是什么类型,那么计算出来的结果就是什么类型
        // 算术运算符的注意点-参与运算的操作数是什么类型,那么计算出来的结果就是什么类型
        int value3 = 1 / 2;
        printf("value3的值是%i
    ",value3); // 打印出来的是0
        // 此时你会不会觉得是因为定义的变量是int类型导致的呢?那我就换成double类型的看看
        double value3 = 1 / 2;
        printf("value3的值是%lf
    ",value3); // 打印出来的是0.000000 此时还是0
        // 是因为右侧参与运算的都是整数,那么计算的结果肯定是整数
    
    
         // 那么如果需要打印出0.5该怎么办呢?
        double value4 = 1.0 / 2; // 此时一个double除以int类型,肯定是都先转换为doublee类型,计算出的结果就是double类型,i定义的变量也是double类型不需要转换所以打印出的是0.500000
        printf("value4的值是%.1lf
    ",value4);
        
        int value5 = 1.0 / 2;
        printf("value5的值是%i
    ",value5); // 0
    • 新手注意常犯的错误
        // 新手注意饭的错误
        double value6 = (double)(1 / 2);
        // 右边先计算括号中的1 / 2,那么两个整数相除,结果肯定是整数,所以是0 ,由强转为double类型,为0.000000
        printf("value6的值是%lf",value6); // 0.000000
    • 在算术运算符中,实数的计算都是double类型,不是float类型

    赋值运算符

    • 最简单的赋值运算符,将等号右边的值赋值给等号左边的变量
      • 赋值运算符的结合性是右结合性
    int main(int argc, const char * argv[]) {
        // 最简单的赋值运算符,将等号右边的值赋值给等号左边的变量
        // 赋值运算符的结合性是右结合性
        int number = 10;
        int a;
        int b;
        a = b = 5;
        printf("a的值是%i,b的值是%i
    ",a,b);
        return 0;
    }
    • 符合赋值运算符
      • 定义:在赋值符“=”加上其他的二目运算符可构成复合赋值运算符

    赋值运算符的作用是将常量、变量或表达式的值赋给某一个变量。

    运算符术语示例结果
    = 赋值 a=2; b=3; a=2; b=3;
    += 加等于 a=0; a+=2; a = a + 2 a=2;
    -= 减等于 a=5; a-=3; a = a - 3 a=2;
    *= 乘等于 a=2; a*=2; a = a * 2 a=4;
    /= 除等于 a=4; a/=2; a = a / 2 a=2;
    %= 模等于 a=3; a%2; a = a % 2 a=1;
        int a = 0;
        a += 3; // 这种是直接进行赋值,运算效率要好
        a = a +3; // 这一种是不是先计算再赋值给a
        printf("a的结果是%i
    ",a);
    // 复合赋值运算,会先进行右边的表达式得到的值在赋值给左边的变量

    自增,自减运算符

    • 自增自减的第一种写法: 变量++,变量--
        int result = 10;
        result++;
        result++;
        printf("变量++,自增后的result值为:%i
    ",result); // 12
        // 如果想让某一个数减1,可以使用变量--,--变量
        int value = 5;
        value--;
        printf("变量--,自增后的value值为:%i
    ",value); // 4
    • 自增自减的第二种写法: --变量,++变量
    // 第二种写法:++变量,--变量
        int result1 = 10;
        ++result1;
        printf("++变量,自增后的result1值为:%i
    ",result1); // 11
        
        int result2 = 5;
        --result2;
        printf("++变量,自增后的result1值为:%i
    ",result2); // 4
    • ​ ++,-- 在变量前面和++,-- 在变量后面的区别(在变量之前先运算再自增,在变量之后先自增再运算)
        // ++,-- 在变量前面和++,-- 在变量后面的区别
        // ++ , -- 在后面时,先参与运算然后再自增
        int a = 10;
        int b = a++;
        printf("a的值是%i,b的值是%i
    ",a,b);// a的值是11,b的值是10 注意看b的值是10,而不是11,这里是a先赋值给b,然后再自增的
        
        // ++ --在变量之前时,是先自增再赋值
        int c = 10;
        int d = ++c;
        printf("c的值是%i,d的值是%i
    ",c,d); // c的值是11,d的值是11 注意看这里d的值同样是11,所以c是先自增再赋值给d
    • 自增,自减练习
        // 练习
        /*
        int a = 10;
        int b = (a++) + (++a);
        //  b = a++ ,此时a++的结果是11, 后面++a在a=11的基础上再自增,那么a的值就是12了,10+12
        //  a =12
        printf("b的值是%i,a的值是%i
    ",b,a);
        */
        /*
        int a = 10;
        int b = (a++) + (a++);
        printf("b的值是%i,a的值是%i
    ",b,a); // b = 10 + 11 , a = 12
        */
        /*
        int a = 10;
        int b = (++a) + (++a);
        printf("b的值是%i,a的值是%i
    ",b,a); // b = 11 + 12 ,a = 12
        */
        /*
        int a = 10;
        int b = (++a) + (a++);
        printf("b的值是%i,a的值是%i
    ",b,a); // b = 11 + 11, a = 12
        */
        int a = 10;
        int b = (a++) + (a--);
        printf("b的值是%i,a的值是%i
    ",b,a); // b = 10 + 11 , a = 10
    • 自增的拆分
        // 自增的拆分
        int a = 10;
        int b = a++;
        // 拆分:
        // 1, int b = a;
        // 2, int a = a+1;
        printf("b的值是%i,a的值是%i
    ",b,a); // b = 10,a = 11
        
        int c = 10;
        int d = ++c;
        // 拆分
        // 1,int c = c + 1;
        // 2,int d = c;
        printf("d的值是%i,c的值是%i
    ",d,c);
        // 拆分之后,只是两个表达式的顺序反了. 如果有时确实难懂的话不妨拆分一下

    sizeof运算符

    • 介绍:sizeof运算符可以用来计算一个变量或一个常量,一种数据类型所占的内存节数

    • 格式:sizeof(变量/常量/数据类型)

    • 注意:sizeof 不是一个函数而是一个运算符(只要是运算符就会有一个返回值)

    • 计算常量的内存字节

        // 使用 sizeof 计算常量的内存字节
        int number = sizeof(10.9);
        printf("10.9的e内存字节是%i
    ",number); // 8
    • 计算变量的内存字节
        int a = 10;
        // int number = sizeof(a); // 只要是运算符就会有返回值
        int number = sizeof a; // 不加s括号e也可以
        printf("a的内存字节是%i
    ",number);
    • 计算数据类型的内存字节(sizeof的括号不能省略)
        // 使用 sizeof 计算数据类型的内存字节
        int numChar = sizeof(char);
        printf("char 数据类型占用%i个字节
    ",numChar); // 1
        int numInt = sizeof(int);
        printf("int 数据类型占用%i个字节
    ",numInt); // 4
        int numDouble = sizeof(double);
        printf("double 数据类型占用%i个字节
    ",numDouble); // 8
        int numFloat = sizeof(float);
        printf("float 数据类型占用%i个字节
    ",numFloat); // 8

    逗号运算符

    • 在 C 语言中逗号也是一个运算符,称之为逗号运算符,其功能是把多个表达式连接起来组成一个表达式,成为逗号表达式

    • 格式: 表达式 1,表达式 2,表达式....表达式 n;

    • 例如:a = a + 1,b = 3*4;

    • 结合性:从左到右结合性

        // 逗号运算符,从左到右依次计算表达式的结果,只要是运算符就会有结果,逗号运算符也不例外
        int a = 10;
        int b = 5;
        int result;
        a = a + 10,b = b - 1,result = a + b;
        printf("a的值是%i,b的值是%i,result 的值是%i
    ",a,b,result);
    • 逗号表达式的结果是最后一个表达式的结果
    // 定一个一个变量 number 来接收逗号表达式的结果,每个表达式用括号括起来,整体再括起来,逗号表达式的结果是最后一个逗号表达式的结果
        int number =  ((a = a + 10),(b = b - 1),(result = a + b));
        printf("a 的值是%i,b 的值是%i,result 的值是%i,number 的值是%i
    ",a,b,result,number);

    关系运算符

    • 在 c 语言中条件成立为真,条件不成立为假,判断条件是否成立就是判断条件的真假
    • 怎么判断条件的真假呢? C 语言中规定任何数值都有自己的真假性,任何非 0 的都为真,也就是说 100,-50,2.3这些都是真,只有 0 是假的
    • 关系运算符的结果只有两个结果,真和假

    C 语言的比较运算中, “真”用数字“1”来表示, “假”用数字“0”来表示。

    运算符术语示例结果
    == 相等于 4 == 3 0
    != 不等于 4 != 3 1
    < 小于 4 < 3 0
    > 大于 4 > 3 1
    <= 小于等于 4 <= 3 0
    >= 大于等于 4 >= 1 1
    • 关系运算符的返回值要么真要么假
        // > , < , >= , <= , == , !=
        int a = 10;
        int b = 5; // 怎么知道 a>b 呢? 任何的运算符都有结果
        int c = 20;
        int result = a > b;
        int result1 = a > c;
        printf("result的值是%i
    ",result); // 1
        printf("result1的值是%i
    ",result1); // 0
    • 关系运算符的优先级: > < >= <=的优先级大于 == , !=
        // 关系运算符的优先级: > < >= <=的优先级大于 == , !=
        int a = 10;
        int b = 5;
        int result = 1 == a > b; // 先计算 a 是否大于 b,再拿这个结果与 1 是否相等,
        printf("result 的值是%i",result); // 1
    • 算术运算符的优先级大于关系运算符(比较运算符)
        // 算术运算符的优先级大于关系运算符
        int result = 1 + 1 > 2+2;
        printf("result 的值是%i
    ",result);  // 0,先计算 1+1,在计算 2+2,再拿 2>4?
    • 关系运算符的结合性是左结合性
        // 关系运算符的结合性是左结合性
        int result = 10 > 5 > 20;
        printf("result 的值是%i
    ",result); // 0,先计算 10>5,再拿这个值与 20做比较
    • 如果优先级和结合性同时存在,那就先优先级,再结合性
        // 如果优先级和结合性同时存在,那就先优先级,再结合性
        int result = 10 + 1 > 5 + 4 == 3 > 1;
        // 先计算 10+1,再计算 5+4,这两个算术运算符,得出 11 > 9 == 3>1
        // 再计算 11 > 9 ,和 3 > 1 这两个优先级比较高的比较运算符表达式,
        // 最后计算 1 == 1 等于的表达式
        printf("result 的值是%i
    ",result); // 11 > 9 == 3 > 1 ---> 1 == 1 ---> 1
    • 开发中没有人会按照上面那么写的
        int result1 = (10+1) > (5+4) == (3>1);
        printf("result1 的值是%i
    ",result1); // h实际开发中为了阅读,还是加上括号

    逻辑运算符

    • 有时候我们需要满足多个条件同时成立才能执行代码,比如登录:需要输入正确的用户名,和正确的密码,才能登录.所以c 语言提供了逻辑运算符

    • C 语言中提供了三个逻辑运算符

      • && 逻辑与 表达式 1 && 表达式 2
      • || 逻辑非 表达式 1 || 表达式 2
      • ! 逻辑非 ! 表达式 2
    • 逻辑运算符的运算结果只有两个真和假

    • 逻辑与:只有表达式都为真,结果才是真,其余都是假

      • 结合性:从左至右
        // 逻辑与(一假则假)
        int result = 10 > 7 && 5 > 3; // 10>7为真,5>3 为真
        printf("result = %i
    ",result); // 1
        int result1 = 10 > 90 && 8 >1; // 10 > 90为假
        printf("result1 = %i
    ",result1); // 0
    • 逻辑或:只要有一个表达式为真,结果就是真,如果表达式都是假,结果才是假
      • 结合性:从左至右
        // 逻辑或 (一真则真)
        int result = 10 > 8 || 9 > 7;
        printf("result = %i
    ",result); // 都为真--真
        
        int result1 = 10 > 8 || 9 > 10;
        printf("result1 = %i
    ",result1); // 一个为真--真
        
        int result2 = 10 > 11 || 9 > 10;
        printf("result2 = %i
    ",result2); // 都为假--假
        
        int result3 = 10 > 11 || 9 > 8;  // 一个为真--真
        printf("result3 = %i
    ",result3);
    • 逻辑非(如果表达式为真,则为假,如果表达式为假,则为真)---取反
      • 结合性:从右至左
        // 逻辑非
        int result = ! 10; // 0
        int result1 = ! 0; // 1
        printf("result = %i
    ",result);
        printf("result1 = %i
    ",result1);
    • 注意点;C 语言规定,任何数值都有真假性,非 0 既真,所有的逻辑运算符可以直接约数值进行计算
    • 逻辑与的特点是一假则假,所以如果前面的表达式是假的话,那么后面的表达式就不会计算了
        int a = 10;
        int result = 10 < 8 && a++ > 5; // a = 10,result = 0
        // 由于 10 < 8 为假,所以后面的表达式就不会计算了,a++ 后,a 的值就没有自增
        int b = 20;
        int result1 = 10 > 8 && b++ >5; // 10 > 8 为真,后面的表达式继续计算,所以 b 的值是 21
        printf("a = %i,result = %i
    ",a,result);
        printf("b = %i,result1 = %i
    ",b,result1);
    • 逻辑或的特点是一真则真,所以如果前面的表达式是真的话,那么后面的表达式就不会计算了
        int a = 10;
        int result = 10 > 8 || a++ > 5; // a = 10,result = 0
        // 由于 10 > 8 为真,所以后面的表达式就不会计算了,a++ 后,a 的值就没有自增
        int b = 20;
        int result1 = 10 < 8 || b++ >5; // 10 < 8 为假,后面的表达式继续计算,所以 b 的值是 21
        printf("a = %i,result = %i
    ",a,result);
        printf("b = %i,result1 = %i
    ",b,result1);
    • 以上两个逻辑运算符的特点称之为:逻辑运算符的短路

    • 判断一个数值是否在一个范围内

        int a = 10;
        if (a > 3 && a < 100){
            printf("a在 3-100 之间");
        } else{
            printf("a 不在 3-100 之间");
        }

    三目运算符

    • 格式: 条件表达式 ? 结果 A: 结果 B

      • 如果表达式为真,返回结果 A,如果表达式为假,返回结果 B
    • 结合性:左结合性

        // 三目运算符
        int a = 10;
        int b = 20;
        int result = a > b;
        printf("result = %i
    ",result);
        // 如果我想获取两个数之间的最大数呢?
        if (a>b){
            printf("a 和 b 之间最大数是%i
    ",a);
        }else{
            printf("a 和 b 之间最大数是%i
    ",b);
        }
        // 可是上面的办法太麻烦了,x要写这么多行代码
        int maxNum = a > b ? a:b; // 这句话的意思是,如果a> b,那就返回 a,如果 a 不大于 b 的话,那就返回 b
        printf("a 和 b 之间最大数是%i
    ",maxNum);
    • 三目运算符练习
        // 从控制台输入三个整数,返回最大的整数
        printf("请输入三个整数以逗号隔开,回车结束
    ");
        int num1,num2,num3;
        scanf("%i,%i,%i",&num1,&num2,&num3);
        int temp = num1 > num2 ? num1 : num2; // 比较 num1 和num2 中的最大值
        int maxNum = temp > num3 ? temp : num3; // 拿到 num1 和 num2 的最大值再与 num3 做比较,返回最大值
        printf("num1,num2,num3 之间的最大值是:%i
    ",maxNum);
        
        int maxNum1 = (num1 > num2 ? num1 : num2) > num3 ? (num1 > num2 ? num1 : num2) : num3;
        // 不推荐这种写法是因为,问号之前计算了一次num1 和num2 的最大值,问号表达式之后又计算了一次,无疑消耗了性能
        printf("num1,num2,num3 之间的最大值是:%i
    ",maxNum1);
  • 相关阅读:
    leetcode 18 4Sum
    leetcode 71 Simplify Path
    leetcode 10 Regular Expression Matching
    leetcode 30 Substring with Concatenation of All Words
    leetcode 355 Design Twitte
    leetcode LRU Cache
    leetcode 3Sum
    leetcode Letter Combinations of a Phone Number
    leetcode Remove Nth Node From End of List
    leetcode Valid Parentheses
  • 原文地址:https://www.cnblogs.com/zcyd/p/14000699.html
Copyright © 2011-2022 走看看