C语言 操作符

逊嘘 2024-08-07 11:35:02 阅读 76

       操作符分多种:算术操作符,移位操作符,位操作符,赋值操作符,单目操作符,关系操作符,逻辑操作符,条件操作符,逗号表达式,下标引用,函数调用和结构成员,表达式求值。 

算术操作符 

加法(+):执行两个操作数的加法运算。减法(-):执行两个操作数的减法运算。乘法(*):执行两个操作数的乘法运算。除法(/):执行两个操作数的除法运算。如果两个操作数都是整数,则执行整数除法;如果包含浮点数,则执行浮点数除法。取余(%):获取两个整数操作数相除后的余数。

移位操作符

二进制中有三种表现式原码,反码,补码。内存中存储是补码且移位的也是补码。

     正数的原码,反码,补码是相同的

     例:正数(int整型占四个字节(32bit)。一个字节等于八个比特位)

     原码——00000000000000000000000000001010(10)

     反码——00000000000000000000000000001010(10)

     补码——00000000000000000000000000001010(10)

    

     负数的原码,反码,补码要经过计算的

     反码是符号位不变,其他位按位取反,就是反码。补码是反码+1  

     例:负数

     原码——10000000000000000000000000001010(10)

     反码——11111111111111111111111111110101

     补码——11111111111111111111111111110110

1.左移操作符(<<)

左边舍弃,右边补0。 

下面是正数时

<code>int main()

{

int a = 10;//a为正数时

//00000000000000000000000000001010(a的补码)

int b = a << 1;

//00000000000000000000000000010100(b的补码)

printf("a=%d\n", a);//10

printf("b=%d\n", b);//20=a*2^1

return 0;

}

 负数时:

int main()

{

int a = -10;//a为负数时

//10000000000000000000000000001010(a的原码)

//11111111111111111111111111110101(a的反码)

//11111111111111111111111111110110(a的补码)

int b = a << 1;

//11111111111111111111111111101100(a左边舍弃右边补0即为b的补码)

//10000000000000000000000000010011

//10000000000000000000000000010100(b的原码)

printf("a=%d\n", a);//-10

printf("b=%d\n", b);//-20=a*2^1

return 0;

}

2.右移操作符(>>)

 1.算术右移[平常见到](右边舍弃,左边补原来的符号位)

 2.逻辑右移                (右边舍弃,左边直接补0)

正数时:

int main()

{

int a = 10;

//00000000000000000000000000001010

int b = a >> 1;

//00000000000000000000000000000101(算术右移)

//00000000000000000000000000000101(逻辑右移)

printf("a=%d\n", a);

printf("b=%d\n", b);

return 0;

}

负数时:

int main()

{

int a = -1;

//10000000000000000000000000000001(a的原码)

//11111111111111111111111111111110(a的反码)

//11111111111111111111111111111111(a的补码)

int b = a >> 1;

//11111111111111111111111111111111(b的补码)

//10000000000000000000000000000000

//10000000000000000000000000000001(b的原码)

printf("a=%d\n", a);

printf("b=%d\n", b);

return 0;

}

位操作符

1.按位与(&)

 对应二进制位有0为0,两个同为1为1。

int main()

{

int a = 10;

//00000000000000000000000000001010

int b = -5;

//10000000000000000000000000000101

//01111111111111111111111111111010

//01111111111111111111111111111011

int c = a & b;

//00000000000000000000000000001010(a)

//01111111111111111111111111111011(b)

//00000000000000000000000000001010(c)

printf("c=%d\n", c);

return 0;

}

2.按位或(|)

 对应二进制位有1为1,两个同为0为0。

int main()

{

int a = 10;

//00000000000000000000000000001010

int b = -5;

//01111111111111111111111111111011

int c = a | b;

//00000000000000000000000000001010(a)

//01111111111111111111111111111011(b)

//01111111111111111111111111111011(c)

printf("c=%d\n", c);

return 0;

}

3.按位异或(^)

对应二进制位相同为0,相异为1 。

int main()

{

int a = -5;

//01111111111111111111111111111011

int b = 10;

//00000000000000000000000000001010

int c = a ^ b;

//01111111111111111111111111111011

//00000000000000000000000000001010

//01111111111111111111111111110001

printf("c=%d\n", c);//-15

return 0;

}

 赋值操作符

简单赋值(=):将右侧操作数的值赋给左侧操作数。复合赋值:如+=、-=、*=、/=、%=、<<=、>>=、&=、|=、^=等,它们在赋值的同时执行相应的算术或位操作。 

 单目操作符 

逻辑非(!):对操作数进行逻辑非操作,如果操作数为真(非零),则返回假(0);如果操作数为假(0),则返回真(1)。取地址(&):获取变量的地址。间接引用(*):通过指针访问其所指向的值。自增(++)自减(--):分别使操作数的值增加或减少1。它们有前置和后置两种形式,前置形式在操作数被使用之前执行增减操作,后置形式则在操作数被使用之后执行。sizeof:计算操作数的类型长度(以字节为单位)。~:对一个数的二进制按位取反。(类型):强制类型转换。

关系操作

相等(==):检查两个操作数是否相等。不等(!=):检查两个操作数是否不相等。大于(>)小于(<)大于等于(>=)小于等于(<=):分别用于比较两个操作数的大小关系。

逻辑操作符 

逻辑与(&&):如果两个操作数都为真,则返回真;否则返回假。逻辑与具有短路特性,即如果第一个操作数为假,则不会评估第二个操作数。(见假即假)逻辑或(||):如果两个操作数中至少有一个为真,则返回真;否则返回假。逻辑或同样具有短路特性也就是第一个操作数为真,不会再计算后面的操作数。(见真即真)

条件操作符 

条件(表达式1?表达式2:表达式3):也称为三目操作符,用于根据条件表达式的真假来选择两个表达式中的一个进行计算。

 逗号表达式

逗号(,):用逗号隔开的多个表达式从左向右依次执行,整个表达式的结果是最后一个表达式的结果。

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

下标引用([ ]):用于访问数组的元素。成员访问(. 和 ->):<code>.(点操作符)用于访问结构体或联合类型的成员,->(箭头操作符)用于访问指向结构体或联合类型的指针的成员。

表达式求值 

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

截断:在实际表示中(比如在内存中),二进制数的开头可能不会有前导零(除非是为了对齐或特定格式的要求)。

隐式类型转换:C的整型算术运算总是至少以缺省整型类型的精度来进行的。 为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升

 

<code>int main()

{

char ch1 = 24;

//00000000000000000000000000011000

//00011000 (取出一个字节即八个bit)————————截断

//00000000000000000000000000011000一个字节中首位为符号位,则八个bit外剩下的bit全部补符号位

char ch2 = 100;

//00000000000000000000000001100100

//01100100

//00000000000000000000000001100100

char ch = ch1 + ch2;

//00000000000000000000000000011000 ch1——————整型提升

//00000000000000000000000001100100 ch2

//然后就是一位一位相加 64+32+16+8+4=124

//00000000000000000000000001111100 (内存中为补码)

//11111111111111111111111110000011 (先取反后加一)

//11111111111111111111111110000100 原码

//00000000000000000000000001111011 (先减一后取反)

//11111111111111111111111110000100 原码

//同样取一个字节10000100

//11111111111111111111111110000100 (补码)

//11111111111111111111111110000011

//00000000000000000000000001111100 ch原码————————124

printf("%d\n", ch);

return 0;

}

 下面例举有符号char类型的取值范围的由来。之所以八个bit位因为char的字节为一(一个字节等于八个bit位),相同如果需要计算short的取值范围则需要16个bit位(两个字节),int则需要32个bit位(四个字节)等等。无符号的更简单一些,首位不是符号位而是有效位。

算术转换 :如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类 型,否则操作就无法进行。下面的层次体系称为寻常算术转换。

 

操作符的属性 :复杂表达式的求值有三个影响的因素。 1. 操作符的优先级 2. 操作符的结合性 3. 是否控制求值顺序。(相邻两个操作符才有优先级)

写表达式时尽量不要写的模棱两可(即问题代码),能简单写简单写。 



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。