<--
如果你觉得我写的分享对你有帮助,请点个赞
<--
如果你觉得我写得有错误,请点个踩并在评论区指出!
<--
如果你想在之后再次看这篇分享,请点下这个星星!
初始化
INITIALIZE
上一篇提到了 memset
的基本用法,这次的内容包含计算机底层的运算和用 memset
初始化时的(bu)常用数值。
目录
第一章 C++ 存储数据方式
- 1.1 bit 和 byte
- 1.2 原码、反码、补码
- 1.3 位运算
第二章 初始化
- 表格
本文中的 int
和 unsigned int
类型变量、数组均占用 4 个字节,且数组类型默认为 int
。
本文中的 long long
类型变量、数组均占用 8 个字节。
一个数前面带 0x
说明该数是十六进制。
第一章 C++ 存储数据方式
1.1 bit 和 byte
比特位,即 bit,是计算机最小的存储单位。
bit 包含 0 和 1 两种状态。计算机进行运算,就是靠一个个 bit 的变化。
计算机存储数据就是使用二进制进行存储,每一位都是一个 bit,网上有许多关于二进制的解释,这里就不再赘述。
字节(Byte)是计算机信息技术用于计量存储容量的一种计量单位,由 8 个 bit 组成,可以表示 0∼255 的无符号整数。
1.2 原码、反码、补码
以下是 32 位(4 字节)的二进制数的存储方式,即 C++ 里的 int
和 unsigned int
来介绍计算机的整数存储和运算。
原码
一个数的原码的最高位是符号位,0代表正数,1代表负数;原码的非符号位为该数字绝对值化为二进制。
如:
- +13 的原码为 00000000 00000000 00000000 00001101 (四字节)
- -19 的原码为 10000000 00000000 00000000 00010011 (四字节)
- -31 的原码为 10000000 00000000 00000000 00011111 (四字节)
- -48 的原码为 10000000 00000000 00000000 00110000 (四字节)
反码
正数的反码与原码一致;负数的反码是对原码按位取反,只有最高位(符号位)不变。
如:
- +13 的反码为 00000000 00000000 00000000 00001101 (四字节)
- -19 的反码为 11111111 11111111 11111111 11101100 (四字节)
- -31 的反码为 11111111 11111111 11111111 11100000 (四字节)
- -48 的反码为 11111111 11111111 11111111 11001111 (四字节)
补码
正数的补码与原码一致;负数的补码是这个数的反码加 1,最高位(符号位)不变。
如:
- +13 的补码为 00000000 00000000 00000000 00001101 (四字节)
- -19 的补码为 11111111 11111111 11111111 11101101 (四字节)
- -31 的补码为 11111111 11111111 11111111 11100001 (四字节)
- -48 的反码为 11111111 11111111 11111111 11010000 (四字节)
对于一个有符号整数(int
),它的存储方式为存储补码。
那么为什么要使用补码进行存储呢?
在补码下,每个数值都有唯一表示方式(使用原码则 0 将会有两种表示方式),且 32 位补码下任意两个数值做加减运算(符号位进位后舍弃),都等价于两个数值做加减法运算,从而简化运算规则。
1.3 位运算
四种最基本的位运算如下:
与 | 或 | 非 | 异或 |
---|---|---|---|
& |
| |
~ |
^ |
与: 对于任意一位,两个运算数同为真结果为真,否则结果为假
或: 对于任意一位,两个运算数有一个为真结果就为真,否则结果为假
非: 对于任意一位,运算数该位真则结果为假,假则结果为真
异或: 对于任意一位,两个运算数该位不同为真,该位相同为假
按位左移 | 按位右移 |
---|---|
<< |
>> |
以上是 C++ 的按位移动运算。
a << b
:将该数 a 左移 b 位,正数左移后为正数,负数左移后为负数
a<<b=a×2b
a >> b
:将该数 a 右移 b 位,正数右移后为正数,负数右移后为负数。不论正负,都下取整
a>>b=a/2b
更多内容请转去这里:链接
第二章 初始化
表格
- 表格中的数表示执行
memset(a, x, sizeof(a));
后 a 数组内每个数的值 - 若 “x” 列是“无”,赋值时用
a[i] = y
的方式赋值,y 可以填“十六进制”一列的数
类型 int
:
x | 32 位补码 | 十进制 | 十六进制 | 性质 |
---|---|---|---|---|
0 | 0000…0000 | 0 | 0x00000000 | 常用初始化,每一项都为 0 |
0x3F | 00111111重复四次 | 1061109567 | 0x3F3F3F3F | 见下文 |
0x7F | 01111111重复四次 | 2139062143 | 0x7F7F7F7F | 是 memset 能够赋值的最大 int 数值 |
无 | 0111…1111 | 2147483647 | 0x7FFFFFFF | 是最大的 int 整数 |
无 | 1000…0000 | -2147483648 | 0x80000000 | 是最小的 int 整数 |
0x80 | 10000000重复四次 | -2139062144 | 0x80808080 | 是 memset 能够赋值的最小 int 数值 |
0xAF | 10101111重复四次 | -1347440721 | 0xAFAFAFAF | 小于 −109 |
0xC0 | 11000000重复四次 | -1061109568 | 0xC0C0C0C0 | 和 x = 0x3F 作用类似,只不过是负数 |
0xFF | 1111…1111 | -1 | 0xFFFFFFFF | 常用初始化,每一项都为 −1 |
int
类型下的 0x3F3F3F3F 是一个非常有用的数值,一般用于表示无穷大:
- 它的两倍并不超过 0x7FFFFFFF,意味着不会在将其加倍时出现负数;
- 它的二分之一是 530554783(0x1F9F9F9F),大于 5×108;
- 它的每个字节都是相同的,可以用
memset
赋值。
$\\\$
类型 unsigned int
:
x | 32 位补码 | 十进制 | 十六进制 |
---|---|---|---|
0 | 0000…0000 | 0 | 0x00000000 |
0x3F | 00111111重复四次 | 1061109567 | 0x3F3F3F3F |
0x7F | 01111111重复四次 | 2139062143 | 0x7F7F7F7F |
无 | 0111…1111 | 2147483647 | 0x7FFFFFFF |
无 | 1000…0000 | 2147483648 | 0x80000000 |
0xFF | 1111…1111 | 4294967295 | 0xFFFFFFFF |
如果用 unsigned int
,可以用 0x7F7F7F7F 作为无穷大。
$\\\$
类型 long long
:
x | 64 位补码 | 十进制 | 十六进制 |
---|---|---|---|
0 | 0000…0000 | 0 | 0x0000000000000000 |
0x3F | 00111111重复八次 | 4557430888798830399 | 0x3F3F3F3F3F3F3F3F |
0x7F | 01111111重复八次 | 9187201950435737471 | 0x7F7F7F7F7F7F7F7F |
无 | 0111…1111 | 9223372036854775807 | 0x7FFFFFFFFFFFFFFF |
无 | 1000…0000 | -9223372036854775808 | 0x8000000000000000 |
0x80 | 10000000重复八次 | -9187201950435737472 | 0x8080808080808080 |
0xFF | 1111…1111 | -1 | 0xFFFFFFFFFFFFFFFF |
其实这些值都没啥用hh