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. 是否控制求值顺序。(相邻两个操作符才有优先级)
写表达式时尽量不要写的模棱两可(即问题代码),能简单写简单写。
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。