计算机如何区分 '\0'(空字符)和“unsigned int = 0”?

Ang*_*xus 30 memory

如果在给定的情况下,您有一个字符数组(当然以空字符结尾),紧接着在内存中的下一个位置,您想将其存储0为 unsigned int,计算机如何区分这些二?

Jam*_*han 87

它没有。

字符串终止符是一个包含所有 0 位的字节。

unsigned int 是两个或四个字节(取决于您的环境),每个字节都包含所有 0 位。

这两个项目存储在不同的地址。您编译的代码在前一个位置执行适合字符串的操作,在后者执行适合无符号二进制数的操作。(除非你的代码中有错误,或者一些危险的聪明代码!)

但是所有这些字节在 CPU 看来都是一样的。内存中的数据(在大多数当前常见的指令集架构中)没有任何类型与之关联。这是一个只存在于源代码中的抽象,并且只对编译器有意义。

编辑添加:例如:对组成字符串的字节执行算术运算是完全可能的,甚至是常见的。如果您有一个 8 位 ASCII 字符的字符串,您可以通过加减 32(十进制)将字符串中的字母在大小写之间转换。或者,如果您要转换为另一个字符代码,您可以将它们的值用作数组的索引,该数组的元素在其他代码中提供等效的位编码。

对于 CPU 而言,字符实际上是超短整数。(每个 8 位,而不是 16、32 或 64。)对我们人类来说,它们的值碰巧与可读字符相关联,但 CPU 不知道这一点。它也对“空字节结束字符串”的“C”约定一无所知(并且正如许多人在其他答案和评论中指出的那样,在某些编程环境中根本不使用该约定) .

可以肯定的是,x86/x64 中有一些指令经常与字符串一起使用 - 例如 REP 前缀 - 但如果它们达到预期的结果,您也可以在整数数组上使用它们。

  • @gronostaj 您的评论有点令人困惑:与 C 不同,C++ 字符串也会自动处理这个问题。C++ 通常也不被归类为低级语言(甚至 C 有时也不是)。 (18认同)
  • 这就是为什么开发人员必须小心使用字符串。如果您有 100 个连续字节,则最多可以容纳 99 个 1 字节字符以及最后一个字节中的终止符。如果你在那里写一个 100 字节的字符串,程序将无法确定字符串在那里结束,并会继续读取连续的字节,直到巧合的零字节。如果字符串长度超过 100 字节,它将覆盖一些相邻的数据。高级编程语言(Java、C#、JS 等)自己处理这个问题,但在 C、C++、汇编等低级语言中,这是开发人员的责任。 (14认同)
  • @JamieHanrahan IA64 处理器 [有点叫 NaT](https://blogs.msdn.microsoft.com/oldnewthing/20040119-00/?p=41003)(或“不是一件事”),如果设置了一个值。 (8认同)
  • 有(旧的)CPU 体系结构在数据值上具有类型标记,因此将整数取消引用为指针会产生异常。 (5认同)
  • @KonradRudolph“自动”并不意味着“万无一失”,当然不是在 C++ 中 (4认同)
  • @KonradRudolph:C++ 可以使用隐式长度的 C 字符串。`std::string` 的一些构造函数采用 `const char*` 参数。如果你用 `read()` 或 `recv()` 系统调用完全填满了先前清零的缓冲区,然后愚蠢地使用 `basic_string( const CharT* s)` 构造函数而不是指针/长度或 `basic_string(InputIt首先,InputIt last)` 构造函数使用`read` 的长度返回值,你会遇到问题。许多 C++ 程序/库并不存在于 C++ 乌托邦中,在那里它们只使用 `std::string` 与惯用的 C++ 函数/数据交互。 (3认同)
  • 重新“字符串终止符是一个包含所有 0 位的字节。”,这并不普遍。取决于语言:'\0' 终止符是从 C 继承的。不过,在 Fortran 中,字符串本质上是一个具有单独长度字段的结构。较新的语言似乎基本上使用一种或另一种 - 或有时两者兼而有之,例如在 C++ 中,您可以使用普通的 C“以'\0'”字符串结尾的字符数组,或包含隐藏数据(如长度)的 C++ 字符串类。其他语言可能会使用不同于... (2认同)
  • @KonradRudolph 低级/高级区别是模糊的。与asm相比,即使是C也是高级的。如今,当大多数软件建立在网络技术或其他垃圾收集平台上时,任何让您意外覆盖相邻内存区域的东西都可以说是低于平均水平的。这就是我写评论时的意思。10 年后,我们可能会认为 Java 是低级的,因为它通常需要所有样板。松散相关的有趣事实:https://superuser.com/questions/638675/why-does-ram-have-to-be-volatile/638694#comment798457_638694 (2认同)
  • “*这是一种抽象,[...] 只对编译器有意义。*” - 我希望对程序员也是如此。 (2认同)

Bra*_*one 5

简而言之,没有区别(除了 int 为 2 或 4 个字节宽,而 char 仅为 1)。

问题是所有现代库要么使用空终止符技术,要么存储字符串的长度。在这两种情况下,程序/计算机在读取空字符或读取了大小告诉它的字符数时都知道它到达了字符串的末尾。

当空终止符丢失或长度错误时,这个问题就开始了,因为程序开始从它不应该的内存中读取。

  • 哦,short 是有区别的——实际上,short 作为一种非常依赖机器的数据类型而臭名昭著:) (3认同)