🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀
目录
🐰算数操作符:+ - * / %
🐰移位操作符:<< >>
🌸进制的定义
🌸整数二进制表示形式
🌸<< 左移操作符
🌸>>右移操作符
🐰位操作符:& | ^
🌸&(按位与)|(按位或)
🌸^(按位异或)
🐰赋值操作符: =
🐰复合赋值符:+= -= *= /= %= <<= >>= &= != ^=
🐰单目操作符:! - + & * ~ -- ++
🐰关系操作符:> >= < <= != ==
🐰逻辑操作符:&& ||
🐰条件操作符:exp1?exp2:exp3(三目操作符)
🐰逗号表达式:exp1,exp2,exp3,…,expN
🐰下标引用操作符 [ ]
🐰函数调用操作符 ( )
🐰结构成员访问操作符
🐰运算符的优先级顺序表
🐰隐式类型的转换-整形提升
/:除法——得到的是商。 除法操作符的两个的操作数都是整数的话,执行的是整数除法。 除法操作符的两个的操作数 只要一个是浮点数 ,执行的是小数数除法。 例如:9/2 就是整数除法 9/2.0或者9.0/2.0 就是小数除法%:取模(取余)——得到的是余数 ‼️注:取模操作符的两个个操作数必须为整数
移位操作符(移动的是二进制的位)<<:左移操作符 >>:右移操作符
10进制的数据中:都是0~9的数字组成 2进制的数据:0~1的数字组成 8进制的数据:0~7的数字组成 16进制的每一位:0 1 2 3 4 5 6 7 8 9 a b c d e f (2进制,8进制,10进制,16进制只不过是数值的表达形式而已) 例如:数值10 1010 2进制 12 8进制 10 10进制 a 16进制
整数的二进制表示形式有三种: 原码、反码、补码 ,正数的原、反、补码是相同的,只有负数的原、反、补码需要转换。 转换规则 原码:把一个数按照正负直接翻译成二进制就是原码 反码:原码的符号位不变,其他位按位取反 补码:反码+1 ‼️ 注:原、反、补码的最高位是符号位例如:5 -5是整数,一个整形变量是4字节32比特位 5 原码:00000000000000000000000000000101 反码:00000000000000000000000000000101 补码:00000000000000000000000000000101 -5 原码:10000000000000000000000000000101 反码:11111111111111111111111111111010 补码:11111111111111111111111111111011‼️注:整数在内存中存储的是补码
<<左移操作符: 左边抛弃,右边补0 例如:int a=3; int b=a<<1; a:00000000000000000000000000000011(补码) a<<1:00000000000000000000000000000110 b:00000000000000000000000000000110 int a=-3 int b=a<<1; a: 原码:10000000000000000000000000000011 反码:111111111111111111111111111111111111111100 补码:111111111111111111111111111111111111111101 原码到补码:取反,+1(符号位不变) 补码到原码:-1,取反(符号位不变)和取反,+1(符号位不变) a:111111111111111111111111111111111111111101 a<<1:111111111111111111111111111111111111111010 b:111111111111111111111111111111111111111010
1:>>算术右移(左边用原来的符号位填充,右边丢弃) 2: >>逻辑右移(左边直接用0填充,右边丢弃) 右移的时候,到底采用的是算术右移?还是逻辑右移,是取决于编译器的(常见的是算术右移) ‼️注:对于移位操作符,不要移动负数位,这个是标准未定义的 例: Int a=10; a<<-1(错误)
位操作符:&(按位与) |(按位或) ^(按位异或)
‼️注:位是二进制位,操作数必须是整数
&:相同为相同的数,相异为0
int a=3 b=-5 ;a:00000000000000000000000000000011 3的补码 b:10000000000000000000000000000101 11111111111111111111111111111010 11111111111111111111111111111011 -5的补码 a&b:00000000000000000000000000000011|: 相同为相同的数,相异为1a|b:11111111111111111111111111111011 a^b:11111111111111111111111111111000
异或:相同为0,相异为1 规则 (异或支持交换律的) : a^a=0 0^a=a a^a^b=b a^b^a=b 例题 交换a和b的值,不能用第三个变量#includeint main() { int a=3; int b=5; a=a^b;//000000000011^000000000101=000000000110(6) b=a^b;//000000000110^000000000101=00000000011(3) //b=a^b^b=a a=a^b;//000000000110^00000000011=00000000101(5) //a=a^b^a return 0; }
a=b=c+1;//连续赋值(可读性较低)
~:按位取反(二进制) 例:int a=0 a:00000000000000000000000000000000 ~a:11111111111111111111111111111111 补码 11111111111111111111111111111110 反码 10000000000000000000000000000001 原码 ~a=-1‼️注:While(~scanf(“%d”,&a)),scanf读取失败会返回EOF,就是-1,-1按位取反则是0--:前置:先使用,再--,后置:先使用,再--
++:前置:先使用,再++,后置:先使用,再++
int a=10,b=0; //b=a++;//后置++:先使用,再++,先把a=10值赋给b,然后a再++,a=11,b=10; //b=++a;//前置++:先++,再使用,a先++,a=11,然后把a=11赋值给b,b=11; b=a--; b=--a;
逻辑操作符关注真假(1和0),&&(逻辑与)和||(逻辑或)
例:
int i=0,a=0,b=2,c=3,d=4; i=a++&&++b&&d++;//如果左边为假,后面就不需要算了 printf("a=%d b=%d c=%d d=%d i=%d\n",a,b,c,d,i); 结果为:a=1 b=2 c=3 d=4 i=0,因为a++,是后置++,所以此时a值为0,则后后面的不需要计算,就为初始值 i=a++||++b||d++;//如果左边为真,后面就不需要算了 printf("a=%d b=%d c=%d d=%d i=%d\n",a,b,c,d,i); 结果为:a=1 b=3 c=3 d=4 i=0,因为++b前置++,此时b值不为0,所以后面的d不会进行计算。
int a=5,b=3,c=0; c=a>b?a:b
例如两数中求最大值 #includeint main() { int a=3,b=5; int max=a>b?a:b return 0; }
数组里常用,arr[ ],arr[ i ]...
Int len=strlen(“abc”); Int Add(3,5)//3,5就是( )的操作数
(1). 结构体变量.结构体成员名
(2)-> 结构体指针->结构体成员
struct S { int num; char c; }; void test(struct S* ps ) { printf(“%d”,(*ps).num); printf(“%c”,(*ps).c) printf(“%d”,ps->num);//只有结构体指针才能使用-> printf(“%c”,ps->.c) } int main() { struct S s={100,’b’}; printf(“%d\n”,s.num); printf(“%c\n”,s.c); test(&s) return 0; }
优先级 | 操作符(运算符) | 名称 | 使用原型 | 结合规律 | 注释 |
| [ ] | 数组下标 | 数组名[常量表达式] | 从左到右 | |
( ) | 小括号 | (表达式)/(强制转换类型) | |||
. | 成员选择(对象) | 对象.成员名 | |||
-> | 成员选择(指针) | 指针->成员名 | |||
| ! | 逻辑反操作符(逻辑非) | !表达式 | 从右到左 | 单目运算符 |
- | 负值 | -表达式 | |||
+ | 正值 | +表达式 | |||
& | 取地址运算符 | &变量名 | |||
* | 间接访问操作符(解引用操作符) | *指针变量 | |||
~ | 按位取反操作符 | ~表达式 | |||
-- | 自减运算符 | --变量名/变量名-- | |||
++ | 自加运算符 | ++变量名/变量名++ | |||
sizeof | 长度运算符 | sizeof(表达式) | |||
(类型) | 强制类型转换 | (数据类型)表达式 | |||
| / | 除 | 表达式/表达式 | 从左到右 | 双目运算符 |
* | 乘 | 表达式*表达式 | |||
% | 取模(取余) | 整形表达式%整形表达式 | |||
| + | 加 | 表达式+表达式 | ||
- | 减 | 表达式-表达式 | |||
| << | 左移 | 变量<<表达式 | ||
>> | 右移 | 变量>>表达式 | |||
| > | 大于 | 表达式>表达式 | 从左到右 | 双目运算符 |
>= | 大于等于 | 表达式>=表达式 | |||
< | 小于 | 表达式<表达式 | |||
<= | 小于等于 | 表达式<=表达式 | |||
| == | 等于 | 表达式==表达式 | ||
!= | 不等于 | 表达式!=表达式 | |||
| & | 按位与 | 表达式&表达式 | 从左到右 | 双目运算符 |
| ^ | 按位异或 | 表达式^表达式 | ||
| | | 按位或 | 表达式|表达式 | ||
| && | 逻辑与 | 表达式&&表达式 | ||
| || | 逻辑或 | 表达式||表达式 | ||
| ?: | 条件运算符 | 表达式1?表达式2:表达式3 | 从右到左 | 三目运算符 |
| = | 赋值运算符 | 变量=表达式 | 从右到左 | |
/= | 除后赋值 | 变量/=表达式 | |||
*= | 乘后赋值 | 变量*=表达式 | |||
%= | 取模后赋值 | 变量%=表达式 | |||
+= | 加后赋值 | 变量+=表达式 | |||
-= | 减后赋值 | 变量-=表达式 | |||
<<= | 左移后赋值 | 变量<<=表达式 | |||
>>= | 右移后赋值 | 变量>>=表达式 | |||
&= | 按位与后赋值 | 变量&=表达式 | |||
^= | 按位异或后赋值 | 变量^=表达式 | |||
|= | 按位或后赋值 | 变量!+表达式 | |||
| , | 逗号运算符 | 表达式,表达式... | 从左到右 |
‼️注:同一优先级的运算符,顺序由结合规律所决定
整形提升是按照变量的数据类型的符号来提升的
(1)负数的整形提升
char c1=-1;
变量c1的二进制位(补码)中只有8个bit位;
11111111
因为char为有符号的char
所以整形提升的时候,高位补充符号位,即为1
提升之后的结果是:
111111111111111111111111111111111
(2)正数的整形提升
char c2=1;
变量是c2的二进制(补码)中只有8个bit位;
00000001
因为char为有符号的char
所以整形提升的时候,高位补充符号位,即为0
提升之后的结果是:
00000000000000000000000000000001
(3)无符号整型提升,高位补0
例题:
int main() { char a=3; //00000000000000000000000000000011-都是补码 //000000111-截断 char b=127; //00000000000000000000000001111111 //01111111-截断 char c=a+b; //00000000000000000000000000000011 //00000000000000000000000001111111 //00000000000000000000000010000010 //运算时整形提升 //10000010 //赋值给c时又发生截断 printf("%d\n",c); //10000010 //11111111111111111111111110000010-补码 //11111111111111111111111110000001-反码 //10000000000000000000000001111110-原码 //所以打印出的值为10000000000000000000000001111110(二进制),-126(十进制) //%d打印整型提升 return 0; }
🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸