移位操作符
不要移动负位数
只针对整数
<< 左移操作符
//16进制 //0~9 a~f //2进制 //0~1 //整数的二进制表示有三种 //原码 //反码 //补码
//正的原码、反码、补码相同
//负的原码、反码、补码要计算
//7的二进制(整型要占四个字节.32个比特位,一个字节8个比特位)
00000000000000000000000000000111
//最高位即最前面的数表示符号位,0为正,1为负
00000000000000000000000000000111 -原码
00000000000000000000000000000111 -反码
00000000000000000000000000000111 -补码
//-7
10000000000000000000000000000111 -原码
11111111111111111111111111111000 -反码 (原码的符号位不变,其他取反)
11111111111111111111111111111001 -补码 (反码+1)
//整数在内存中存储的是补码 补码-->反码-->原码
对正数操作
//左移操作符
//移动的是二进制
//左边丢弃,右边补0
int a = 7;
int b = a << 1;
printf("a=%d \nb=%d\n", a, b);
对负数操作
//左移操作符
//移动的是二进制
//左边丢弃,右边补0
int a = -7;
int b = a << 1;
printf("a=%d \nb=%d\n", a, b);
左移有乘2的效果
右移操作符 >>
-
算术移位(右边抛弃,左边补原符号位)
-
逻辑移位(右边抛弃,左边补0)
大多数的编辑器都是采用算术移位
移位操作符不能移负数
按位操作符
& - 按(2进制)位与
| - 按(2进制)位或
^ - 按(2进制)位异或
位操作符&所操作的是对二进制操作(整数是4字节,一个字节是8个bit )
按位与0操作符的操作规则
将整数的二进制的补码进行位与操作符,两个二进制出现0为0.都为1才是1
int a = 3;
int b = -5;
int c = a & b;
printf("c=%d\n", c);
return 0;
按位或1操作符
将整数的二进制的补码进行位与操作符,两个二进制出现1为1.都为0才是0
int a = 3;
int b = -5;
int c = a | b;
printf("c=%d\n", c);
return 0;
异或操作符
相同位0,相异位1---支持交换律
int a = 3;
int b = -5;
int c = a ^ b;
printf("c=%d\n", c);
return 0;
//两个相同的数字异或操作符位0 0与其他数异或为本身
//3^3 = 0 5^5 = 5 0^a=a
//011 000
//011 101
//000 101
使用案例
在不创建临时变量(第三个变量),实现两个数的交换
使用异或操作符
//这种方法在+的时候会出现溢出的现象
int a = 3;
int b = 5;
printf("交换前:a=%d,b=%d\n", a, b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("交换前:a=%d,b=%d\n", a, b);
编写代码,计算一个数的二进制中1的个数
思路:
a&1后为0说明二进制最后一个位为0,为1说明为1,之后再用右移操作符。
单目操作符
只有一个操作数
+
a+b双目操作符
~ 按二进制取反
int a = 13;
//要求将1101中间的0换为1
//00000000000000000000000000001101 13的2进制补码
//00000000000000000000000000000001 1的补码
//将1左移后位或13
//00000000000000000000000000000010
//00000000000000000000000000001111 15
int n = 0;
printf("输入改变的位次:\n");
scanf("%d", &n);
printf("操作前a=%d\n",a);
a |= (1 << n);
printf("操作后a=%d\n", a);
a &= (~(1 << n));
printf("还原a=%d\n:", a);
return 0;
++
前置++,先++,后使用
int a = 3;
int b = ++a;//前置++,先++,后使用
printf("a=%d\n", a);
//a = a+1,b=a; a先++再赋值
printf("b=%d\n", b);
return 0;
后置++
int a = 3;
int b = a++;
printf("a=%d\n", a);//后置++,先使用,再++
//b = a ; a = a+1; 先进行赋值,再++
printf("b=%d\n", b);
return 0;
int c = 10;
test(c++);//这里传值是10,之后c再++变为11
间接访问操作符(解引用操作符)
常与指针使用
int a = 10;
int* p = &a;
*p = 20; //p里面存了a的地址,*p通过a的地址访问到a的内容
printf("a=%d\n", a);
return 0;
(类型)
强制类型转换
int a = (int)3.14;
逻辑操作符
&& 左边为假,右边就不计算
|| 左边为真,右边就不计算
int i = 0, a = 0, b = 2, c = 3;
i = a++ && ++b && c++;//短路运算符 a =0 直接结束
printf("i = %d\na = %d\nb = %d\nc = %d\n",i, a, b, c);
return 0;
条件操作符
表达式1成立表达式2否则表达式3
逗号表达式
从左到右依次执行,整个表达式的结果是最后一个表达式的结果
可以把do-while循环中do的结构体放入while中
while(a = test, count(a),a>0)
{
//业务处理
}
下标引用操作符[ ],函数调用操作符()和结构成员
arr[7]
//[]的操作数为arr和7
//相当于5 + 3
arr[7] -->*(arr+7)
arr[7] --> 7[arr]
test();//函数调用操作符,操作数:test
//结构成员访问
struct Stu
{
char name[20];
int age;
double score;
};
void set_stu(struct Stu* ps)
{
strcpy(ps ->name, "zhangsan"); //结构体指针->成员
ps->age = 20;
ps->score = 100.0;
}
void print_stu(struct Stu ss)
{
printf("%s %d %lf\n",ss.name,ss.age,ss.score); //结构体对象.成员
}
int main()
{
struct Stu s = { 0 };
set_stu(&s);
print_stu(s);
return 0;
}
ps->age等价于(*ps).age