<< 左移操作符
>> 右移操作符
移位操作符的操作数只能是整数
移(2进制)位操作符
原码-------符号位不变,其他位按位取反--->反码----+1--->补码
补码转换为原码:取反,+1
左移操作符:左边丢弃,右边补0.
算数右移(大部分):右边丢弃,左边补原来的符号位。
逻辑右移:右边丢弃,左边直接补0.
位操作符:
& //按位与
| //按位或
^ //按位异或
注:他们的操作数必须是整数。
异或操作符:
1.a^a=0
2.0^a=a
3.异或支持交换律
整数的2进制表达形式有三种:原码,反码,补码
内存中存储的起始是:补码的二进制,所以在参与移位的时候,移动后都是补码。
12—数值
//2进制:1100
8进制:14
16进制:c
注意:
1.按照一个数的正负,直接写出它的二进制表示形式得到的就是原码。
2.正数的原码,反码,补码是相同的。
3.反码是原码的符号位保持不变,其他位按位取反。就是反码。
4.补码是反码+1
5.整型占4个字节(32bit)
&--按2进制位与:对应的二进制位有0,则为0,两个同时为1才为1.
|--按2进制位与:对应的2进制位有1则为1,两个同时为0才为0.
^--按2进制位异或:相同为0,相异为1.
面试题:不创建临时变量,实现两个整数的交换。
int main()
{
int a=3;
int b=5;
a=a+b;//a=a^b;
b=a-b;//b=a^b
a=a-b;//a=a^b;
printf("%d %d\n",a,b);
return 0
}
sizeof和数组
数组传参,形参可以写成数组,也可以写成指针。即使写成数组,本质上也是指针。
sizeof内部的表达式是不计算的
sizeof(arr)或sizeof(ch)都为4或8
逗号表达式
int a = 1;
int b = 2;
int c = (a > b, a = b + 10, a, b = a + 1);//依次计算,值为最后一个表达式的值。
char --1字节–8bit 范围是:-128~127
整型提升
只要参加表达式运算,就要发生整型提升。
整型提升的意义:表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器的操作数的字节长度一般就是int的字节长度 ,同时也是CPU的通用寄存器长度。
因此,即使两个char类型的相加,在cpu执行时也要先转换为cpu内整型操作数的标准长度。通用cpu是难以直接实现两个8bit字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整数值。都必须先转换为int或unsigned int,然后才能送去CPU去执行运算。
如何进行整型提升?
无符号的整型提升,高位补0.
#include
int main()
{
char a = 0xb6;//10110110-->11001001-->1100101-->1111111111111111111111111100101
short b = 0xb600;//1011011000000000-->1100100111111111-->11111111111111111100100111111111
int c = 0xb6000000;
if (a == 0xb6)
printf("a");
if (b == 0xb600)
printf("b");
if (c == 0xb6000000)
printf("c");//a和b需要进行整型提升,变成了负数,所以前两个if为假。但c不发生整型提升。
return 0;
}
int main()
{
char c = 1;
printf("%u\n", sizeof(c));
printf("%u\n", sizeof(+c));//c参与表达式运算,发生整型提升。
printf("%u\n", sizeof(-c));
return 0;
}
结果是:1 4 4
算术转换
若某个操作符的各个操作数属于不同类型,那么除非其中一个操作数转换为另一个操作数的类型,否则操作无法进行。下面的层次体系称为寻常算数转换。
long double
double
float
unsigned long int
long int
unsigned int
int
从下往上转换
如果某个操作数类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。
注意:算术转换要合理!!!
float f=3.14;
int num=f;//隐式转换,会有精度丢失。
操作符的属性
复杂操作符的求值有三个影响的因素:
1.操作符的优先级。
2.操作符的结合性。
3.是否控制求值顺序。
两个相邻的操作符先执行哪个?取决于他们的优先级,若优先级相同,取决于它们的结合性。