算术操作符: + 、- 、* 、/ 、%
移位操作符: << >>
位操作符: & | ^ `
赋值操作符: = 、+= 、 -= 、 *= 、 /= 、%= 、>= 、&= 、|= 、^=
• 单⽬操作符: !、++、--、&、*、+、-、~ 、sizeof、(类型)
关系操作符: > 、>= 、< 、<= 、 == 、 !=
逻辑操作符: && 、||
条件操作符: ? :
逗号表达式: ,
下标引⽤: []
函数调⽤: ()
结构成员访问: . 、 ->
上面的这些操作符中,我们在前面的博客已经讲过算术操作符、赋值操作符、逻辑操作符、条件操作符和部分的单目操作符,继续介绍另一部分,但是在这之前我们要知道一下二进制和进制转换的知识。
我们之前知道有很多进制,其实这些进制就是数组的不同表示形式而已。
比如:数值15的各种进制的表现形式:
15的2进制:1111
15的8进制:17
15的10进制:15
15的16进制:F
在讲二进制的时候我们首先要先从10进制来讲起,10进制在我们的生活中经常用。
10进制满10进1 10进制的数字每一位都是0-9的数字组成
二进制中满2进1 2进制的数字每一位都是0-1的数字组成
我们通过观察不难发现,10进制数其实就是字从右向左是个位、⼗位、百位....,分别每⼀位的权重是 10 , 10 , 10 ...
2进制和10进制是类似的,只不过2进制的每⼀位的权重,从右向左是: 2 , 2 , 2 ... 0 1 2
10进制的125转换的二进制:1111101
8进制的数字每⼀位是0~7的,0~7的数字,各⾃写成2进制,最多有3个2进制位就⾜够了,⽐如7的⼆ 进制是111,所以在2进制转8进制数的时候,从2进制序列中右边低位开始向左每3个2进制位会换算⼀ 个8进制位,剩余不够3个2进制位的直接换算。(转2从右3个二进制为一组不够时左边补0)
如:2进制的01101011,换成8进制:0153,0开头的数字,会被当做8进制。
16进制的数字每⼀位是0~9,a ~f 的,0~9,a ~f 的数字,各⾃写成2进制,最多有4个2进制位就⾜够了, ⽐如 f 的⼆进制是1111,所以在2进制转16进制数的时候,从2进制序列中右边低位开始向左每4个2进 制位会换算⼀个16进制位,剩余不够4个⼆进制位的直接换算。(转2从右边4个为一组,不够时补0)
如:2进制的01101011,换成16进制:0x6b,16进制表⽰的时候前⾯加0x
在整数的2进制表示方法有3种,即原码、反码和补码。有符号整数的三种表⽰⽅法均有符号位和数值位两部分,2进制序列中最高位为符号位,其余都是数值位。
符号位都是⽤0表⽰“正”,⽤1表⽰“负”。
int num=10;
//10是存放在整型变量num中,占4个字节==32bit位
//0 0000000000000000000000000001010
| |
符号位 数值位
正整数的原、反、补码都相同。
负整数的三种表示⽅法各不相同。
原码:直接将数值按照正负数的形式翻译成⼆进制;
反码:将原码的符号位不变,其他位依次按位取反;
补码::反码+1就得到补码;
注:反码得到原码也可以直接使用:取反,+1的操作。
(记住,对于整型来说:数据存放内存中其实存放的是补码)
<< 左移操作符
>> 右移操作符
注:移位操作符的操作只能是整数。
移位规则:左边抛弃、右边补0
比如; 有int num=10,执行num<<
移位规则:⾸先右移运算分两种:
(右移是逻辑右移还是算术右移,是取决于编译器的实现!!!,大部分的编译器是算术右移)
#include
int main()
{
int num = 10;
int n = num>>1;
printf("n= %d\n", n);
printf("num= %d\n", num);
return 0;
}
& //按位与
| //按位或
^ //按位异或
~ //按位取反
注:它们的操作数必须是整数。
代码使用:
#include
int main()
{
int num1 = -3;
//10000000000000000000000000000011——原码
//11111111111111111111111111111100——反码
//11111111111111111111111111111101——补码
int num2 = 5;
//00000000000000000000000000000101——补码
printf("%d\n", num1 & num2);//按(2进制)位与(只要有0就是0,两个同时为1才是1)
printf("%d\n", num1 | num2);//按(2进制)位或(只要有1就是1,两个同时为0才是0)
printf("%d\n", num1 ^ num2);//按(2进制)位异或(相同位0;相异为1)
printf("%d\n", ~num2);//按(2进制)位取反(补码取反)
return 0;
}
实践的运用:
不能创建临时变量(第三个变量),实现两个数的交换。
#include
int main()
{
int a = 5;
int b = 3;
//a = a + b;
//b = a - b;
//a = a - b;
这种写法的缺陷是:a和b如果非常大,求和后结果超过了整型的最大值
a = a ^ b;
b = a ^ b;
a = a ^ b;
//异或的特点
//a^a=0;
//0^a=a;
printf("a=%d b=%d\n", a, b);
return 0;
}
练习1:求⼀个整数存储在内存中的⼆进制中1的个数。
#include
int main()
{
int a = 3;//如果考虑负数的话就写位int unsinged int a;
int count = 0;
int i = 0;
for (i = 0; i < 32; i++)
{
if (((a >> i) & 1) == 1)//a&1=1说明a的二进制最后一位为1,反之为0;
{
count++;
}
}
printf("%d ", count);
//方法2:
while (a)
{
if (a % 2 == 1)
{
count++;
a /= 2;
}
}
printf("%d ", count);
//方法3
while (a)
{
a = a & (a - 1);
count++;
}
printf("%d ", count);
return 0;
}
练习2:⼆进制位置0或者置(编写代码将13⼆进制序列的第5位修改为1,然后再改回0)
#include
int main()
{
int n = 13;
int a = n | (1 << 4);
int b=n& ~(1 << 4);
printf("%d %d\n", a, b);
return 0;
}
单⽬操作符有这些: !、++、--、&、*、+、-、~ 、sizeof、(类型)
逗号表达式,就是⽤逗号隔开的多个表达式。
exp1, exp2, exp3, …expN
逗号表达式,从左向右依次执⾏。整个表达式的结果是最后⼀个表达式的结果。
操作数:⼀个数组名 + ⼀个索引值
int arr[10];//创建数组
arr[9] = 10;//实⽤下标引⽤操作符。
[ ]的两个操作数是arr和9。
#include
void test1()
{
printf("hehe\n");
}
int main()
{
test1(); //这⾥的()就是作为函数调⽤操作符。
return 0;
}