C语言运算符
1.算术运算符
+、-、/、%、++,如下:(浮点类型数据不能取余!)
这是因为float类型不能取余从而报错
前++、前-- 运算规则:先运算,后自增\自减
int a = 1, b = 2;
a = b++;
printf("a == %d, b == %d\n", a, b);
// a == 2, b == 3
后++、 后-- 运算规则:先自增\自减,后运算
int a = 1, b = 2;
a = ++b;
// a == 3, b == 3
2.关系运算符
> , >= , < ,<=, !=(不等于)
非零为真
注意 = 和 == 是不一样的
= 是向左赋值,改变左值
== 是判断是否相等,结果是真假值
3.逻辑运算符
逻辑运算的结果只有真假值,&&的优先级比||高,优先执行;
3.1逻辑非 “ !”:取反
在下面这段程序中a-b的值取反不等于7,所以最后输出的结果为false
在下面这段代码对括号内(错误的)的结果取反,得到的为真。
3.2逻辑与 “ &&”:短路特性-逢0截至
左运算量 | 右运算量 | 结果 |
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
根据上面两幅图的代码发现,下面一副图的代码a和b的值并没有发生改变,这是因为逻辑与 “ &&”的短路特性-逢0截至。在第6行中因为逻辑与 “ &&”的短路特性所以并没有执行b++和a++,所以最后a和b的值并没有发生改变。
3.3逻辑或 “ || ”:短路-逢1截至
左运算量 | 右运算量 | 结果 |
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
在这副图中,因为逻辑或 “ || ”的短路-逢1截至的特性,所以a的值最后并没有发生改变。
4.位运算符
运算符 | 功能说明 | 举例 |
~ | 位逻辑反 | ~a |
& | 位逻辑与 | a&b |
| | 位逻辑或 | a|b |
^ | 位逻辑异或 | a^b |
>> | 右位移 | a<<1 |
<< | 左位移 | b>>4 |
在上面这幅图中,x的二进制一开始为00010111,然后进行位取反之后为11101000。在输出的代码中%x表示输出16进制数,#为加上前缀0x。
上面图中代码为位逻辑与演示。
上面图中代码为位逻辑或演示。
4.1位逻辑异或:
左运算量的位值 | 右运算量的位值 | 结果 |
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
上面图中代码为位逻辑异或演示。
位移位运算的一般形式:
<运算符><运算量><表达式>其中:
<运算量>必须为整型结果数值
<运算符>为左位移(<<)或(>>)右位移运算符
<表达式>也必须为整型结果数值。
上面图中代码为位移位运算演示。
一开始x的值为0xe4
1 | 1 | 1 | 0 | 0 | 1 | 0 | 0 |
左位移三位后:
0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
最后的结果是:0x20
左位移一位相当于数值×2(前提原数值(正整数)的最高位的1不会消失)
4.2位运算符的应用
无符号数的某位快速置1:
如:x=0x4,想把x的第二位置1(从右到左)
0x4二进制表示:
0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
最后想表达的结果:0x6
0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
想得到这个结果就要让x和00000010进行位逻辑或运算。
从这个代码中可以得到:想要无符号数 x 的 y 位置 1 ,就可以让 x 和(1<<(y-1))位逻辑或运算。
无符号数的某位快速置0:
如:x=0x14,想把x的第三位置0(从右到左)
0x14二进制表示:
0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 |
最后想表达的结果:0x10
0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
想得到这个结果就要让x和11111011进行位逻辑与运算。11111011可以让00000100取反得到。
从这个代码中可以得到:想要无符号数 x 的 y 位置 0,就可以让 x 和(~(1<<(y-1)))位逻辑与运算。
利用位运算把一个十进制转化成一个十六进制数:
用位进行运算
5.赋值运算符“ = ”
一般形式:<左表达式> = <右表达式>
赋值符合运算符:<变量><操作符> = <表达式>
运算符 | 功能说明 | 示例 |
+= | 加赋值运算符 | a+=b等价于a=a+b |
-= | 减赋值运算符 | a-=b等价于a=a-b |
*= | 乘法赋值运算符 | a*=b等价于a=a*b |
/= | 除法赋值运算符 | a/=b等价于a=a/b |
%= | 求余赋值运算符 | a%=b等价于a=a%b |
&= | 位与赋值运算符 | a&=b等价于a=a&b |
|= | 位或赋值运算符 | a|=b等价于a=a|b |
^= | 位异或赋值运算符 | a^=b等价于a=a^b |
>>= | 位右赋值运算符 | a>>=b等价于a=a>>b |
<<= | 位左赋值运算符 | a<<=b等价于a=a<<b |
6.条件运算符“ ?”
是三目运算符,其运算的一般形式是:
< 表达式1> ? :
先运算表达式1,如果表达式1成立就输出表达式2的结果,否则输出表达式3的结果。
7.逗号运算符
z=(x=3,y=2,x+y) :从左到右运算,括号里最右边的结果为整个逗号运算符的结果然后赋值给z。
8.sizeof运算符
运算的一般形式:sizeof()(需要注意的是:它只针对数据类型,而不针对变量)
如:sizeof(int)
9.运算符优先级
可以在网上找一个很多的
10.原码、反码、补码(以1字节的数据类型演示)
计算机存储数据都是转化成补码形式存储。
原码:数据转换成二进制形式(有符号带符号位)
反码:原码除符号位,数据位每个都取反。
补码:反码+1,不影响符号位。
1.有符号类型,最高位是符号位,其他7位为数据位。
符号位区分:0 表示正数,1 表示负数负数的原码符号位1,其他位正常表示;反码是原码符号
位不变,其他位取反;补码是反码加1,不影响符号位
正数的原码、反码、补码, 都是原码的形式
1 000000 0 000000
2.无符号类型,所有都是数据位,没符号位,都是原码的形式。
0~255
10进制 -1 在计算机(二进制)里怎么转换成补码的:
原码 1 000 0001 (十进制转二进制)
反码 1 111 1110 (原码除符号位外,其他位取反得到)
补码 1 111 1111 (反码基础上加1)
10进制 -0
原码 1 000 0000
反码 1 111 1111
补码 1 000 0000 (**进位时不能动符号位**,变补码时加1溢出了,注意就没影响符号位)
因为有了符号位,表示0的时候出现了+0 和 -0,所以规定-0 以后是 -128 //1000 0000
例子:
char ch1 = 129;
输出:-127
原因:
有符号数据129
// 129 原码 反码 补码
1000 0001 → 1000 0001 →
1000 0001 → ↓
1000 0001 → 11111110 →11111111
数据以补码形式存储,符号位上是1,被当做负数读取。
unsigned char ch1 = -1;
输出:255
有符号数据-1 原1000 0001, 反1111 1110, 补11111111
数据以补码形式存储进无符号类型ch1,符号位当做数据读取。