本文对C语言各种操作符以及算术转换.整形提升.操作符属性进行讲解,耐心看完,编程技术更上一层楼~

详解C语言操作符

  • 操作符分类—-下
  • 一.关系操作符
    • 1.关系操作符介绍
      • ①.>and>=关系操作符
      • ③!=and==关系操作符
    • 2.关系操作符总结
  • 二.逻辑操作符
    • 1.逻辑操作符介绍
      • ①.&&逻辑与操作符
      • ②.||逻辑或操作符
      • ③逻辑操作符易错点–短路原则
    • 2.逻辑操作符总结
  • 三.条件操作符
    • 1.条件操作符介绍
      • ① exp1 ” />
        上图用if else演示关系操作符的使用,对if–else结构不熟悉的可以看这篇博客->传送门
        此时a里面为2,b里面为0,a>b表示为2>0关系表达正确返回真,表达式为真则运行下面分支打印>
        同理a>=b也是真也会运行下面语句>=,else表示的是表达式为假即a<b时才会运行的部分

        小于和小于等于和数学里符号表示一样

        a里为0,b里为2,满足if括号里表达式 是关系操作符 为真则运行下面分支 < 和<=

        ③!=and==关系操作符

        !=为不等于,==为等于,这两个操作符和数学中表达方式不同

        从图中看到a里为0,b里为2,c里面为2
        if后面表达式为a!=b 表示为0!=2是真则运行下面语句,a= =b为假则不打印a= =b,
        b= =c表示为2= =2为真则打印b= =c
        但最后一个表达式a=0,本来想表达a等于0 而a里面为0 表达式是为真的,但是写成了一个=号,此时一个等号表示赋值将a变量里的值赋为0,此时0表示假则不会运行这个分支的内容,
        所以用关系操作符等于号时要仔细,避免因为习惯写成了一个等号!!

        2.关系操作符总结

        大部分关系操作符都和数学上表达关系的符号一样,最后得到的结果是真或者假的逻辑值,注意写= =时不要写成了=

        二.逻辑操作符

        && 逻辑与
        || 逻辑或

        1.逻辑操作符介绍

        &&逻辑与和||逻辑或用于判断两边表达式的逻辑关系
        注意区分 &&和&,||和|之间的关系

        ①.&&逻辑与操作符

        A&&B 表示当A和B同时为真时运算结果为真否则返回假

        图中a为0,b为2,c为2,a!=b&&b==c这个表达式表示 当a不等于b且b等于c时为真则运行下面分支

        ②.||逻辑或操作符

        A||B表示A和B中只要有一个表达式为真则运算结果就为真,否则则为假

        图中a != b||b==c表示 a不等于b,b等于c有一个表达式为真则这个式子为真运行下面分支,
        此时两个if的表达式里都有a= =b所以每个表达式都为真两个分支都会运行.

        ③逻辑操作符易错点–短路原则

        使用逻辑操作符有个特点,当计算机已经知道整个表达式最终结果则不会进行没有意义的运算.

        刚开始a为0,b为2,c为2,这个表达式c = ((a = 0) &&( b = 5));先运行a=0将a里面赋值为0,此时a为0,0表示假 而&&表示两边表达式同时为真则为真,否则为假,此时左边表达式已经为假,不管右边表达式b=5是真是假,整个表达式都为假,计算机已经得出了这个表达式的最终结果,不会做多余的运算即不会运算b=5,此时 表示为a=0且 (a = 0) &&( b = 5)这个结果为假则为0,此时将c=0,最后得出的结果为a被赋为了0,b没有改变还是开始的2,c被赋值了表达式后得出的假值->0.得出a=0 b=2,c=0

        2.逻辑操作符总结

        逻辑操作符用于两边表达式的真假进行逻辑运算,使用时要注意短路原则,使用时&&和||不要写成了&和|

        三.条件操作符

        exp1 ” />
        上图中 a为0,而 a?5:3 中 a为0表示假,此时运算第三个表达式也就是3, a?5:3的结果为3 此时被打印出来

        2.条件操作符总结

        条件操作符 使用时要注意运算符优先顺序,多使用括号将式子表达更清晰准确

        四. 逗号表达式

        exp1, exp2, exp3, …expN

        1.逗号表达式介绍

        exp1, exp2, exp3, …expN
        逗号表达式,就是用逗号隔开的多个表达式。
        逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。

        ①exp1, exp2, exp3, …expN逗号表达式


        图中a开始为0,b为2,c为2,逗号表达式(a = 3, b = 5, c = 6)表示先运算将a赋值为3,b赋值为5,c赋值为6,最后得到的逗号表达式结果为c=6,a=c=6然后将a赋值为6 整个表达式使a赋值为3,b赋值为5,c赋值为6,a又赋值为了6,此时输出a=6,b=5,c=6

        2.逗号表达式总结

        逗号表达式运算优先级最低,一般得和括号连用,避免因为运算符优先级造成了错误结果.

        五.下标引用、函数调用和结构成员访问

        [ ] 下标引用操作符
        ()函数调用操作符
        .和->结构成员操作符

        下标引用、函数调用和结构成员介绍

        下标引用作用于数组用于得到数组对应的某个元素,函数调用用于传参调用该函数,结构成员操作符用于访问结构体里的某个成员变量.

        ①[]下标引用操作符


        arr数组里有五个整形元素,数组下标是从0开始的 即arr[0]表示数组第一个元素,而此时arr[3]表示下标为3对应的元素为整形4,此时输出整形4

        ②函数调用操作符


        add(a,b) 里的()表示函数调用操作符,将里面两个参数传参调用这个函数最后返回结果5,

        ③.and->结构成员访问操作符

        结构体为一个自定义类型,它里面自定义多个相同或不同类型的成员变量组成的一个新类型,

        首先创建一个struct stu结构体类型,里面有 一个字符数组 一个整形 两个成员变量,表示名字和年龄
        用这个struct stu类型创建一个变量,此时这个变量涵盖这两个成员变量,对里面的字符数组 年龄分别初始化为张三,18,打印时 通过stu1.name打印这个结构体变量里的名字成员变量,stu1.age打印年龄成员变量 .操作符用于访问结构体变量里的成员变量

        此时创建了一个struct stu* ptu1变量表示 结构体类型的指针变量 存放该stu1结构体变量的指针,
        此时通过ptu1->name 和pstu1->age 访问了 stu1里的名字和年龄变量将其里面的数据打印出来
        ->操作符用于访问结构体指针指向的结构体里面的成员
        pstu1->name等价于(*pstu1),name等价于(stu1).name

        下标引用、函数调用和结构成员访问总结

        这三个操作符分别作用于对应的数组,函数,结构体 操作数,使用时得先了解对应的类型.

        六.表达式求值

        表达式求值的顺序一部分是由操作符的优先级和结合性决定。
        同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型

        1.隐式类型转换

        C的整型算术运算总是至少以缺省整型类型的精度来进行的。
        为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型
        提升。
        整型提升的意义:
        表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度
        一般就是int的字节长度,同时也是CPU的通用寄存器的长度。
        因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长
        度。
        通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令
        中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转
        换为int或unsigned int,然后才能送入CPU去执行运算。

        ①正数的整形提升


        此时定义了一个字符变量ch赋值为12,因为字符变量在内存里占一个字节的空间,而整形12的二进制补码为00000000000000000000000000001100 存放在字符变量里会发生截断,此时ch里存放的是00001100八位二进制位,将ch里的值按整形形式打印出来,此时ch里为八位二进制为,需要整形提升为一个整形32位,按符号位整形提升,此时第八位符号位为0表示正数往后补24个0为00000000000000000000000000001100 此时打印出来的整形为12.

        ②负数的整形提升


        ch为八位的内存空间,-1的二进制补码为11111111111111111111111111111111,此时截断存八位11111111放到ch中,此时以整形形式将ch里的数打印出来,ch里为11111111不足32位按符号为整形提升,此时符号位为1补齐24个1为11111111111111111111111111111111转换为原码为10000000000000000000000000000001打印为整形为-1.

        无符号位的整形提升

        无符号位整形提升左边都补0补齐对应的位数

        #includeint main(){ char a = 511;   //数据发生截断只会留下最右边的8个1在内存里unsigned char b = 511;printf("%u", a); //a先整形提升根据他的类型 是有符号先补符号位32个1 然后得到的这个32个1再根据 打印形式是无符号形式打印 则这32个1就是无符号 最高位是1 为正数原反补转换为十进制就是2 的32减1printf("%u", b);  //b是一个字节 先根据整形提升 b是无符号类型char  整形提升往左补24个0补齐32位 然后得到00000000000000000000000011111111 把这个数当做无符号整形打印则最高位是0原反补相同最后得到的原码整数是255return 0;}

        2.算术转换.

        如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类
        型,否则操作就无法进行。下面的层次体系称为寻常算术转换。
        如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运
        算。
        警告:
        但是算术转换要合理,要不然会有一些潜在的问题

        ①如何算数转换


        这里将整形num里面存放 3.14为double类型双精度浮点型,如果直接赋值是没有意义的,此时会默认将3.14转换为整形,即去掉浮点数则为3,将3赋给num,最后打印出数字3
        但是算术转换不要盲目使用,它会造成精度的损失!!! 比如这里的3.14 变成了3

        七.操作符的属性

        复杂表达式的求值有三个影响的因素。

        1. 操作符的优先级
        2. 操作符的结合性
        3. 是否控制求值顺序。 两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。 操作符优先级

        1.c语言运算符优先级表和介绍


        使用运算符时要根据每个运算符不同的优先级进行运算,当优先级相同时看结合性,表达式不要写太复杂或者多使用括号表明自己想要优先运算的表达式,这样的代码可读性也较好

        2.问题表达式

        因为表达式运行是看相邻操作符优先级,而不相邻操作符之间没有联系,此时不同的编译器会有不同的结果,计算机的运算并不是按从左往右运算.

        这个式子就是一个问题表达式,每个++a运算优先级相同,但都比+号优先,并不能确定它们整体的运算顺序,虽然这里求出了值,但在不同编译器上的值不同,因为每个不同编译器针对这种式子求值顺序不同.写代码因避免写出这种问题表达式,否则你就是猪队友!
        我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题
        的。

        八.总结

        续上篇博客->详解操作符—-上本文介绍了后半部分操作符以及补充了表达式求值.算数转换.整形提升.操作符的属性,我们要熟练运用这些知识,写出高质量的代码~

        写文不易,给个一键三连,支持下吧~~