在回答任何问题之前,请注意
(注意: 根据 n.m.(请参阅 OP 中的评论)“字节 是可写入磁盘的最小数量 使用 C 标准库,非标准库可以很好地处理位或其他任何东西。”所以我在下面所说的关于 WORD 大小是最小的量可能不是很正确,但仍然提供了洞察力) .
NULL 总是 0_decimal(实际上)
dec: 0
hex: 0x00000000
bin: 00000000 00000000 00000000 00000000
虽然它的实际值是由编程语言的规范定义的,所以请在任何地方使用定义的常量NULL 而不是硬编码0(以防万一它发生变化,当地狱冻结时)。
ASCII 字符“0”的编码是 48_decimal
dec: 48
hex: 0x00000030
bin: 00000000 00000000 00000000 00110000
NULL 的概念不存在于文件中,而是存在于生成应用程序的编程语言中。文件中只存在NULL 的数字编码/值。
文件怎么可能在操作中包含空字节
用带有空终止字符串的语言编写的系统(即,
C)?
有了上面的说法,这个问题就变成了,一个文件怎么会包含0?现在答案很简单了。
例如,如果我运行这个 shell 代码:
$ printf "Hello\00, World!"
test.txt $ xxd test.txt 0000000: 4865
6c6c 6f00 2c20 576f 726c 6421 Hello., World!
我在 test.txt 中看到一个空字节(至少在 OS X 中)。如果 C 使用
以空结尾的字符串,而 OS X 是用 C 编写的,那么为什么
文件未在空字节处终止,导致文件
包含Hello 而不是Hello\00, World!?
文件和字符串之间有根本区别吗?
假设一个ASCII字符编码(0到127十进制范围内的1字节/8位字符):
-
字符串是 1 字节字符的缓冲区/字符数组(其中 NULL = 0_decimal 和 '0' = 48_decimal)。
-
文件是 32 位或 64 位“WORDS”的序列(取决于操作系统和硬件,即分别为 x86 或 x64)。
因此,仅包含 ASCII 字符串的 32 位操作系统文件将是 32 位(4 字节)字的序列,范围在十进制值 0 和 127 之间,本质上仅使用 4 字节字的第一个字节(b2:base-2,十进制为 base-10,十六进制为 base-16,仅供参考)
0_b2: 00000000 00000000 00000000 00000000
32_b2: 00000000 00000000 00000000 00100000
64_b2: 00000000 00000000 00000000 01000000
96_b2: 00000000 00000000 00000000 01100000
127_b2: 00000000 00000000 00000000 11111111
128_b2: 00000000 00000000 00000001 00000000
这个字节是最左边还是最右边取决于操作系统的字节顺序。
但要回答您关于 Hello\00, World! 之后缺少的 NULL 的问题,我将假设它已被 EOL/EOF(文件结尾)值取代,这是最可能无法打印,这就是为什么您在输出窗口中看不到它的原因。
注意:我确信现代操作系统(以及经典的基于 Unix 的系统)优化了 ASCII 字符的存储,因此 1 个字(4 个字节)可以打包成4个字符。然而,UTF 改变了,因为这些编码使用更多位来存储字符,因为它们有更大的字母/字符集来表示(比如 50k 汉字/日文字符)。我认为 UTF-8 类似于 ASCII,并且为了统一而重命名(使用 UTF-16 和 UTF-32)。
注意: C/C++ 实际上使用字符数组(即字符串)将 4 个字符“打包”成一个 4 字节的单词。由于每个 char 都是 1 字节,因此编译器将在堆栈或堆上从算术上分配并将其视为 1 字节。因此,如果您在函数中声明一个数组(即自动变量),就像这样
char[] str1[7] = {'H','e','l','l','o','!','\0'};
函数堆栈从地址 1000_b10(base-10/十进制)开始,那么你有:
072 101 108 108 111 033
addr char binary decimal
---- ----------- -------- -------
1000: str1[0] 'H' 01001000 (072)
1001: str1[1] 'e' 01100101 (101)
1002: str1[2] 'l' 01101100 (108)
1003: str1[3] 'l' 01101100 (108)
1004: str1[4] 'o' 01101111 (111)
1005: str1[5] '!' 00100001 (033)
1006: str1[6] '0' 00000000 (000)
由于 RAM 是可字节寻址的,因此每个地址都引用一个字节。