目录
1.操作符的分类
算术操作符:+ 、- 、* 、/ 、%
移位操作符:<< >>
位操作符: & 、 | 、^
赋值操作符:= 、 += 、-= 、*= 、/= 、%= 、 <<= 、>>= 、|= 、^=
单目操作符:! 、 ++ 、-- 、& 、* 、+ 、- 、~ 、sizeof 、(类型)
关系操作符:> 、>= 、< 、<= 、== 、!=
逻辑操作符:&& 、||
条件操作符:? 、:
逗号表达式:,
下标引用:[ ]
函数调用:( )
结构成员访问:. 、->
2.二进制和进制转换
不管是二进制、八进制、十进制还是十六进制,都是数值的不同表现形式而已。
举个例子:
15的二进制:1111
15的八进制:17
15的十进制:15
15的十六进制 :F
2.1 二进制转十进制
十进制的每一位都是有权重的,其数字从左到右依次为个位、十位、百位……,分别的权重是10^0、 10^1、 10^2、……
百位 | 十位 | 个位 | ||
十进制的位 | 1 | 2 | 3 | |
权重 | 10^2 | 10^1 | 10^0 | |
权重值 | 100 | 10 | 1 | |
求值 | 1 * 100 + 2 * 10 + 3 * 1 = | 123 |
二进制和十进制是类似的,只不过二进制的权重从左到右是:2^0 、2^1、2^2 、……
二进制的位数 | 1 | 1 | 0 | 1 | |
权重 | 2^3 | 2^2 | 2^1 | 2^0 | |
权重值 | 8 | 4 | 2 | 1 | |
求值(转换为十进制) | 1 * 8 + 1 * 4 + 0 * 2 + 1 * 1 = | 13 |
2.1.1 十进制转二进制
以125(十进制)为例:
2.2 二进制转八进制和十六进制
2.2.1 二进制转八进制
八进制的数由0~7数字表示,0~7的数字各自写成二进制,最多有3个二进制位就行。
比如7的二进制位111,所以在二进制转八进制数时,从二进制序列中右边低位开始向左每3个二进制位会换算成一个八进制位,剩余不够3个的二进制位直接换算。
如下,二进制的01101011,换算成八进制为:153
二进制 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 |
八进制 | 1 | 5 | 3 |
2.2.2 二进制转十六进制
十六进制的数由0~9,a~f 表示,0~9,a~f (代表10~15)各自写成二进制,最多有4个二进制位就行。
比如 f 的二进制位1111,所以在二进制转十六进制数时,从二进制序列中右边低位开始向左每4个二进制位会换算成一个十六进制位,剩余不够4个的二进制位直接换算。
如下,二进制的01101011,换算成十六进制为:6b
二进制 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 |
十六进制 | 6 | b |
3.原码、反码、补码
整数的二进制表示方法有三种,即原码、反码、补码。
有符号整数的三种表示方法均有符号位和数值位两部分,二进制序列中,最高位的一位被当做符号位,剩余的都是数值位。
符号位用“0”表示“正”,用“1”表示“负”。
正整数的原码、反码、补码都相同。
负整数的三种表达方式各不相同:
原码:直接将数值按照正负数的形式翻译为二进制得到的就是原码。
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码。
补码:反码末位+1就得到补码。
原码转换为补码还有更快的方法:
对于整型来说:数据存放内存中其实存放的时补码。
原码的缺点:符号位不能参与运算,需要涉设计复杂的硬件电路才能处理,费钱!
而用补码,可以将符号位和数值位统一处理;同时,加法和减法也可以统一处理(CPU只有加法器)。
举例:
4.移位操作符
<< 左移操作符
>> 右移操作符
注意:移位操作符的操作数只能是整数
4.1 左移操作符
移位规则:左边抛弃,右边补0
是不是和你一开始想的不太一样?分析如下:
4.2 右移操作符
移位规则:1.逻辑右移:左边用0填充,右边丢弃
2.算数右移:左边用原该值的符号位填充,右边丢弃 (VS上使用的是算数右移)
注意:移动的是补码,打印的是原码。
5.位操作符
位操作符有:
& //按位与
| //按位或
^ //按位异或
~ //按位取反
注意:它们的操作数必须是整数。
5.1 &(按位与)
5.2 |(按位或)
5.3 ^(按位异或)
在不创建临时变量的条件下,实现两个数的交换 :
5.4 ~(按位取反)
5.5 例题
例1:编写代码实现:求一个整数存储在内存中的二进制中1的个数。
#include <stdio.h>
//方法1
int main()
{
int m = 0;
int count = 0;
scanf("%d", &m);
for (int i = 0; i < 32; i++)
{
if ((m >> i) & 1 == 1)
count++;
}
printf("%d\n", count);
return 0;
}
#include <stdio.h>
//方法2
int count_one_bit(unsigned int n)
{
int count = 0;
while (n)
{
if (n % 2 == 1)
count++;
n = n / 2;
}
return count;
}
int main()
{
int num = 0;
scanf("%d", &num);
int n = count_one_bit(num);
printf("%d\n", n);
return 0;
}
#include <stdio.h>
//n = n & (n - 1)
//效果:把n的二进制中最右边的1去掉
//n = 15
//1111 -- n
//1110 -- n-1
//1110 -- n
//1101 -- n-1
//1100 -- n
//1011 -- n-1
//1000 -- n
//0111 -- n-1
//0000 -- n
int count_one_bit(unsigned int n)
{
int count = 0;
while (n)
{
n = n & (n - 1);
count++;
}
return count;
}
int main()
{
int num = 0;
scanf("%d", &num);
int n = count_one_bit(num);
printf("%d\n", n);
return 0;
}
例2:编写代码实现,判断一个数n是否为2的次方数。
#include <stdio.h>
//000001 -- 1
//000010 -- 2
//000100 -- 4
//001000 -- 8
//……
int main()
{
int n = 0;
scanf("%d", &n);
if ((n & (n - 1)) == 0)
printf("Yes\n");
else
printf("No\n");
return 0;
}
6.单目操作符
单目操作符有:
! 、++ 、-- 、& 、* 、+ 、- 、~ 、sizeof、(类型)
单目操作符的特点是只有一个操作数。
7.逗号表达式
exp1, exp2, exp3, exp4
逗号表达式,就是用逗号隔开的多个表达式。
逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的值。
#include <stdio.h>
//代码1
int main()
{
int a = 1;
int b = 2;
int c = (a > b, a = b + 10, b = a + 1);
printf("%d", c);
//c的值为13
return 0;
}
#include <stdio.h>
//代码2
int main()
{
int a = 1;
int b = 2;
int c = 0;
int d = -1;
if (a = b + 1, c = a / 2, d > 0)//真正起作用的是d>0
printf("Yes");
else
printf("No");
return 0;
}
//代码3
a = get_val();
count_val(a);
while (a < 0)
{
//……
a = get_val();
count_val(a);
}
//如果使用逗号表达式,改写为:
while (a = get_val(), count_val(a), a > 0)
{
//……
}