十进制、八进制、十六进制的表示和输出
#include <stdio.h>
int main(int argc, const char * argv[])
{
// 1.默认就是10进制
int num = 12;
// 2.在前面加上一个0就代表八进制
int num1 = 014;
// %d是以十进制的方式输出一个整数
printf("%d\n", num1);
// %o是以八进制的方式输出一个整数
printf("%o\n", num);
// 在数值前面加上0b就代表二进制
int num2 = 0b1100;
printf("%d\n", num2);
// 在数值前面加上0x就代表十六进制
int num3 = 0xc;
printf("%d\n", num3);
// %x是以十六进制的方式输出一个整数
printf("%x\n", num);
// 口诀:不看你怎么存,只看你怎去取
return 0;
}
进制转换
#include <stdio.h>
int main(int argc, const char * argv[])
{
/*
十进制 -> 二进制
9
转换原理:除2取余 倒序读取
9/2 4 1
4/2 2 0
2/2 1 0
1/2 0 1
9 --> 1001
二进制 --> 十进制
1001
转换原理:乘以2的幂数(幂数从0开始), 然后相加
1 * 2(0) = 1
0 * 2(1) = 0
0 * 2(2) = 0
1 * 2(3) = 8
1 + 0 + 0 + 8 = 9
1 1 1 1 1
16 8 4 2 1
N位二进制的取值范围
1位 取值范围 0~1 0~2的1次方-1
2位 取值范围 0~3 0~2的2次方-1
3位 取值范围 0~7 0~2的3次方-1
n位 取值范围 0~2(n)-1
000
001
010
011
100
101
110
111
11111 0~ (32-1)
二进制转换为八进制 进制越大表示的位数就越短
规律:三个二进制位代表一个八进制位
因为3位的最大取值是7 而八进制是逢八进一
1个字节 8位
000 0
001 1
100 4
014
二进制转换为十六进制
规律:四个二进制位代表一个十六进制位
因为4位的最大取值是15, 而十六进制是逢十六进一
0000 0
1100 c
0xc
*/
printf("%d\n", 0b1001);
return 0;
}
原码、反码、补码
内存中存储的是补码。正数的三码一样,负数的补码等于原码取反加一
#include <stdio.h>
int main(int argc, const char * argv[])
{
// int占4个字节 1个字节8位
int num = 12;
/*
// 12的二进制
12在内存中存储的是它的补码
00000000 00000000 00000000 00001100
正数的特点:(三码合一) 正数的原码就是TA的反码就是TA的补码
-12
二进制的最高位我们称之为符号位
如果符号位是0代表是一个正数,
如果符号位是1代表是一个负数
10000000 00000000 00000000 00001100 (-12的原码)
11111111 11111111 11111111 11110011(反码, 符号位不变其它位取反)
11111111 11111111 11111111 11110011
+00000000 00000000 00000000 00000001
_____________________________________________
11111111 11111111 11111111 11110100(补码 , 反码+1)
结论:无论正数负数在内存中存储的都是补码
11111111 11111111 11111111 11110101 (补码)
-00000000 00000000 00000000 00000001 (-1)
_____________________________________________
11111111 11111111 11111111 11110100 (反码)
10000000 00000000 00000000 00001011
*/
printf("%d\n", 0b11111111111111111111111111110101);
return 0;
}
位运算
位运算都是针对二进制的
& 按位与
特点:只有对应的两位都是1才返回1 否则返回0
口诀: 一假则假
规律:任何数按位与上1结果还是那个数
1001
&0101
_______
0001
1001
&1111
______
1001
| 按位或
特点:只要对应的两位其中一位是1就返回1
口诀:一真则真
1001
| 0101
________
1101
^ 按位异或
特点:对应的两位不相同返回1 相同返回0
1001
^ 0101
_______
1100
多个整数按位异或的结果和顺序无关(重要,交换律)
1001
^ 0101
_______
1100
1100
^ 0110
_______
1010
1001
^ 0110
_______
1111
1111
^ 0101
_______
1010
相同整数按位异或结果是0
1001
^ 1001
_______
0000
任何整数按位异或上0结果不变
1001
^ 0000
_______
1001
任何整数按位异或上另一个整数两次结果还是那个数
1001
^ 1001
____________
0000
0000
^0101
______
0101
练习
// int result = 9 & 5;
// int result = 9 | 5;
// int result = 9 ^ 5;
// 多个整数按位异或的结果和顺序无关
// int result2 = 9 ^ 5 ^ 6;
// int result2 = 9 ^ 6 ^ 5;
// 相同整数按位异或结果是0
// int result3 = 9 ^ 9;
// 任何整数按位异或上0结果不变
// int result4 = 9 ^ 0 ;
// 任何整数按位异或上另一个整数两次结果还是那个数
// int result5 = 9 ^ 9 ^ 5;
// int result6 = 9 ^ 5 ^ 9;
// printf("result = %d\n", result6);
~ 按位取反
特点: 0变1 1变0
0000 0000 0000 0000 0000 0000 0000 1001
~1111 1111 1111 1111 1111 1111 1111 0110 (补码)
0000 0000 0000 0000 0000 0000 0000 0001
______________________________________________
1111 1111 1111 1111 1111 1111 1111 0101 (反码)
1000 0000 0000 0000 0000 0000 0000 1010
int result = ~9;
printf("%d\n",0b11111111111111111111111111110110);
<< 左移
a << n 把整数a的二进制位往左边移n位
移出的位砍掉,低位补0, 发现左移会把原有的数值变大
9 << 1 = 18 9 * 2(1) = 18
9 << 2 = 36 9 * 2(2) = 26
9 << n = 9 * 2(n)
左移的应用场景:当要计算某个数乘以2的n次方的时候就用左移,效率最高
注意点:左移有可能改变数值的正负性
>> 右移
a >> n 把整数a的二进制位往右边移n位
移出的位砍掉, 缺少的以为最高位是0就补0是1就补1(是在当前操作系统下)
9 >> 1 = 4 9 / 2(1) = 4
9 >> 2 = 2 9 / 2(2) = 2
右移的应用场景:当要计算某个数除以2的N次方的时候就用右移,效率最高
0000 0000 0000 0000 0000 0000 0000 0000
000000 0000 0000 0000 0000 0000 0000 10
位运算练习(重要)
1、将一个整数以二进制方式输出
要求定义一个函数, 传入一个整数, 输出该整数的二进制
%i %o %x
0000 0000 0000 0000 0000 0000 0000 1001
&0000 0000 0000 0000 0000 0000 0000 0001
// 1.让9的二进制向右移31, 就可以获取到9得最高位的二进制, 然后让9的二进制的最高位和1相&, 那么就可以获得9的最高位
// 2.让9的二进制向右移30, 就可以获得9二进制的第二位
// 3.以此类推, 直到0位置
技巧:
1.任何数与1相&都是那个数
2.利用位移取出每一位
void printBinay(int value)
{
// 1.定义变量需要向右移动的位数
int offset = 31;
// 2.通过循环取出每一位
while (offset >=0) {
int result = (value >> offset) & 1;
printf("%i", result);
// 3.每次取出一位就让控制右移的变量-1
offset--;
if ((offset+1) % 4 == 0) {
printf(" ");
}
}
printf("\n");
}
2、利用位运算符, 判断一个数的奇偶性
// 开发中常用的方式
if (num % 2 == 0) {
printf("偶数\n");
}else
{
printf("奇数\n");
}
1001 9
1011 11
1010 10
1100 12
通过观察, 我们发现如果是偶数, 那么二进制的最后一位是0, 如果是奇数那么二进制的最后一位是1
if ((num & 1))
{
printf("奇数\n");
}else
{
printf("偶数\n");
}
3、交换两个变量的值
a = a ^ b;
b = a ^ b; // b = a ^ b ^ b == a
a = a ^ b; // a = a ^ a ^ b == b
利用异或的性质,可以做加解密
// 用户密码 , 纯数字
int pwd = 123456789;
// 对用户密码进行简单加密
int result = pwd ^ 998;
printf("加密后:%d\n", result);
// 对用户密码进行解密
result = result ^ 998;
printf("解密后:%d\n", result);