1.原码,反码,补码。
正数的原码,反码,补码相等。eg:2的原,反,补码是00000000000000000000000000000010(2进制).
重点讲负数的
例如-2
原码:10000000000000000000000000000010.//最前面的是符号位,1是表示‘-’,如果是‘0’则是‘+’。
反码:1111111111111111111111111111111111101//符号位不变,其余的反过来(1—>0,0—>1)
补码:1111111111111111111111111111111111110//反码+1就是补码
2.位移操作符
左移操作符 <<
规则:右边用原来的符号位填充,左边丢弃。
左移操作符的效果是乘以2 eg:
int a=10;
int b=a<<1//b=20,如果a<<3,这b=10*2^3=80,以此类推。
右移操作符>>
规则:左边用原来的符号位填充,右边丢弃。
右移操作符的效果是除以2
int main()
{
int a = -6;
printf("%d", a >> 1);
return 0;
}///输出‘-3’
补充知识
数据存放和计算在计算机中是以补码的形式,因为CPU只会加法
3.位移操作符:&,|,^,~
& 按(2进制)位与
规则:对应的二进制位只要有0,那么就改为0;全是1则改为1。
int main()
{
int a = 3; int b = -5;
printf("%d", (a & b));
return 0;
}
//00000000000000000000000000000011 3的补码
//10000000000000000000000000000101 -5的原码
//11111111111111111111111111111010 -5的反码
//11111111111111111111111111111011 -5的补码
//00000000000000000000000000000011 3的补码
//11111111111111111111111111111011 -5的补码
//00000000000000000000000000000011 最终结果的补码(因为它是正的,所以不用转换,结果直接就是3).
| 按位或
规则:对应的二进制位只要有1,那么就改为1;全是0则改为0。
int main()
{
int a = 3; int b = -5;
printf("%d", (a | b));
return 0;
}//
//00000000000000000000000000000011 3的补码
//11111111111111111111111111111011 -5的补码
//11111111111111111111111111111011 (最终补码的结果,因为它是负的,所以要通过取反,再加1转化为原码。)------->
//10000000000000000000000000000101 最终结果是-5.
^ 按位异或
规则:对应的二进制位只要相同就为0,不相同则为1.
两个相同的数按位异或的结果是0. 0与任何数按位异或的结果是 原来的数。 (a^a=0, 0^a=a)
int main()
{
int a = 3; int b = -5;
printf("%d", (a ^ b));
return 0;
}//
//00000000000000000000000000000011 3的补码
//11111111111111111111111111111011 -5的补码
//11111111111111111111111111111000 最终结果 -8
~ 按位取反
规则:对所有的二进制位取反(包括符号位)
应用
1.交换两个数(不用创建临时变量)
int main()
{
int a = 3; int b = 9;
printf("交换前a=%d, b=%d\n", a, b);
a = a ^ b;
b = a ^ b;//相当于b=a^b^b; b^b=0,a^0=a,即b=a.
a = a ^ b;//相当于a^a^b,同理可得 a=b.
printf("交换后 a=%d b=%d", a, b);
return 0;
}
2.判断一个数的二进制位上有几个1
int main()
{
int x = 0; scanf("%d", &x); int count = 0;
for (int i = 0; i < 32; i++)
{
if (((x >> i) & 1) == 1)
count++;
}
printf("%d", count);
return 0;
}
3.将任意二进制改为1
int main()
{
int a = 22;//00000000000000000000000000010110
//把第四位改为1,其余的不变。
//00000000000000000000000000010110
// |
//00000000000000000000000000001000 (将1左移三位)
// =
//00000000000000000000000000011110
a = (a | (1 << 3)); printf("%d\n", a);
//将a改变回来
a = (a & (~(1 << 3))); printf("%d", a);
return 0;
}
4.逗号表达式
它的最终结果与最后一个表达式有关。
int a = 1; int b = 3;
int c = (a++, a = 10 + b, b = 1 - a);//最终结果b=-12,所以c的值是-12。
printf("%d", c);
return 0;
int a=1;int b=2;int d=10;
int c=(a++,b=a+10,d=10)//d的最终结果是10
应用
a = get_val();
count_val(a);
while (a > 0)
{
//……
a = get_val();
count_val(a);
}//这样写有点繁琐,可以改成逗号表达式。 如下:
while (a = get_val(), count_val(a), a > 0)
{
//……
}
5.下标访问[],函数调用()
int a[5] = { 1,2,3,4,5 };
printf("%d", a[2]);//[]下标访问操作符,操作数:一个数组名+一个下标。
int add(int x,int y)
{
return x+y;
}
int main()
{
int ret=add(2,4);//()函数调用操作符,函数名add是是操作数,2,3也是操作数。
return 0;
}
6.单目操作符
( + - ++ – & ~ * type sizeof )//自行了解
7.结构体成员访问操作符。
直接访问 .
#include<stdio.h>
struct grade
{
int Math;
int English;
};
struct student
{
char name;
int age;
int ID;
grade G1;//嵌套结构体
}s1, s2, s3;//创建全局结构体变量
int main()
{
student s4 = { 'jack',19,2024099,{121,120} };//初始化
student s5;//创建局部结构体变量
printf("%d\n", s4.age);//.结构体成员访问操作符
printf("%d", s4.G1.English);
}
间接访问
待更新。
8. 操作符的属性
的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。
因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。 通用CPU(general - purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算。
规则:符号位是什么,提升就补什么。
int main()
{
char a = 3;
//提升之前,00000011(最高位符号位是0,及无符号,直接补0)
//提升之后,00000000000000000000000000000011
char b = 127;
//提升之前,01111111
//提升之后,00000000000000000000000001111111
char c = a + b;
//c里面存的是100000010(符号位是1,提升前面全补1)
//提升之后,11111111111111111111111110000010
// (再转换为原码)
//10000000000000000000000011111110
printf("%d", c);
}
算术转换
1.long double
2.double
3.float
4.unsigned long int
5.long int
6.unsigned int
7.int
//规则:向上转换
int a+double b//把int a转换为double a
易错点
表达式1
a*b+c*d+e*f;
//这种表达式有两种计算方式 1.* * * + + 2.* * + * +。大部分情况下可以得到预期结果,但是由于运算顺序不同,如果表达式之间的变量的值会相互影响,就会出错,所以尽量加()
表达式2
int c=4;c+ --c//问题出在左右两边c的值,到底是开始时两边都是4,还是开始时右边是4,--之后再得到左边的c=3?,两种算法j'g不同
d long int
5.long int
6.unsigned int
7.int
//规则:向上转换
int a+double b//把int a转换为double a
### 易错点
表达式1
```C
a*b+c*d+e*f;
//这种表达式有两种计算方式 1.* * * + + 2.* * + * +。大部分情况下可以得到预期结果,但是由于运算顺序不同,如果表达式之间的变量的值会相互影响,就会出错,所以尽量加()
表达式2
int c=4;c+ --c//问题出在左右两边c的值,到底是开始时两边都是4,还是开始时右边是4,--之后再得到左边的c=3?,两种算法j'g不同