进制、编码与内存基础
概念说明
计算机底层并不直接认识“数字 12”“字母 A”或“字符串 hello”。
对它来说,数据最终都是一串二进制位,也就是由 0 和 1 组成的比特序列。
为了方便阅读,程序员经常用不同进制去表示同一份数据:
- 二进制适合直接观察位模式。
- 八进制和十六进制适合压缩表示长二进制串。
- 十进制更适合人类日常理解数量大小。
文字要进入计算机,还需要一套“字符和编号如何对应”的规则,这就是字符编码。
学 C 语言时最常遇到的不是“C 只支持 ASCII”,而是:字符如何存到内存里、一个字符到底占几个字节、字符串为什么要以 '\0' 结尾。
同时还要建立一个基本概念:内存是按字节编址的。
一个字节通常等于 8 位,而变量、数组和结构体最终都要落到一段连续或不连续的内存区域里。后面学 sizeof、数组、指针和文件读写时,这个基础会不断用到。
语法/规则
1 Byte = 8 Bit,位是最小的二进制单位,字节是更常见的存储单位。- 十进制字面量直接写,例如
26;八进制常以前导0开头,例如032;十六进制以0x或0X开头,例如0x1A。 - 标准 C 的整数写法里,
0开头不表示“普通十进制”,而通常表示八进制,这一点非常容易写错。 - 字符编码描述的是“字符与编号的关系”,常见有 ASCII、GBK、Unicode、UTF-8 等。
- 字符串在 C 里本质上是以
\0结尾的字符序列,因此字符串长度和实际占用的数组空间不完全是一回事。 - 内存里的同一串比特,按不同类型解释时可能得到完全不同的含义,这也是类型系统和强制类型转换重要的原因。
- 十六进制在调试中非常常见,因为它和二进制之间转换方便,也很适合观察地址、掩码和字节内容。
示例
| |
输出结果:
| |
这个例子说明了两件事:
同一个整数可以用不同进制显示;字符 'A' 在底层也可以按它的编码值 65 来观察。
常见错误
- 把
012当成十进制 12,实际上它通常会被解释为八进制字面量。 - 以为 C 语言“固定只用 ASCII”,忽略了源文件编码、终端编码和运行环境编码都会影响字符显示。
- 把字符常量
'A'和字符串字面量"A"当成同一种东西来用。 - 忘记字符串末尾还需要一个
\0,导致数组空间预留不够。 - 只会背
KB、MB这些单位,却不知道数组长度、sizeof和文件大小最终都要落回字节这个尺度上理解。