2

我想知道计算机以 1 和 0/低压和高压的形式存储所有信息,yada yada ......但是当我们编译程序时,它 - 或者只是存储在 comp 上的任何数据 - 是二进制形式...那么计算机如何区分 2 条数据,因为它只包含 0 和 1 的流...为了使我的问题更清楚,让我们从 C 中获取一个可笑的简单代码:

void main() {
    int A = 0;
    int* pA = &A;
    char c = 'c';
    char* pC = &c;
    return;
}

它什么也不做——只生成 4 个 int 类型的变量、指向 Int 的指针、char 和指向 Char 的指针……现在这些变量将以 0 和 1 的形式存储在某处……那么,计算机如何知道这样那样的变量从哪个位开始以及在哪里结束?首先,您可能会说计算机有它的地址,好吧,当然。但是最后呢?......那么像对象/结构这样的复杂数据类型呢?

最后但并非最不重要的一点是,函数/程序呢?

4

6 回答 6

4

您现在正在阅读的段落只不过是一串字母和标点符号。你怎么知道一个词在哪里开始和结束?你怎么知道这些词的意思?这个文本流如何传达有用的信息?

你可以对数学说同样的话。当您看到写在页面上的数学表达式时,它们只是一系列数字和符号,但它们是一种以紧凑形式传达深刻思想的强大方式。然后是音乐。那一连串的点、旗子和线条是如何代表像音乐这样短暂的东西的?

答案当然是有规则。这些字母不仅仅是随机组合的——它们有一个特定的顺序。当你遵循你我都知道的规则时,你就能辨别单词,理解它们各自的含义,并将它们组合成思想。

二进制数据也是如此。将数据与随机位区分开来的是存在规则,如果遵循这些规则,则可以以有意义的方式解释位。现在,您已经提出了很多涉及各种规则的问题。试图解释它们会占用比这个答案更合理的空间(并且比我愿意投入的时间更多)。但是如果你拿起一本关于计算机体系结构的书,你会发现关于规则、它们如何工作、它们是如何组织以及它们是如何实现的完整讨论。这真是有趣的东西!

如果您还没有准备好深入研究实际的计算机体系结构,一本可以让您深入了解的优秀书籍是道格拉斯·霍夫施塔特 (Douglas Hofstadter)的《Godel, Escher, Bach: An Eternal Golden Braid》。这是一本厚厚的书,充满了思想。但它也写得很好而且很有趣,你不一定要从头到尾阅读它来学习很多有趣的东西。

于 2012-04-24T16:45:25.407 回答
3

您可以通过尽可能接近金属来回答所有这些问题(以及更多关于计算机的问题):也就是说,学习装配。我建议阅读包含这些主题的装配艺术(在线免费提供)一书。另外,请阅读我对大会学习资源的回答。现在,让我简要回答您的问题:

  • 你是对的,计算机只能看到无穷无尽的比特流。操作系统完成创建文件系统的工作。甚至 ram 也可以被认为是一个非常简单的文件系统(页面或段是文件)。现在什么这意味着操作系统在某个地方有一个表,它可以跟踪每个程序在哪里存储了什么、什么是数据、什么是代码等。

  • 基础级别的变量无非是字节。现在,当你写一个语句时,比如

    a = b + 1

编译器实际上为变量分配了一个任意地址,并将该地址硬编码(即写入实际常量,例如 0xA3F0)到引用它的每个语句。

  • 数据结构的存储方式有很多种。但是,当谈到 c 结构时,事情就更简单了:它们只是一个接一个地存储这个结构包含的变量,如果我们忽略诸如填充之类的东西的话。这就是为什么 a结构的长度总是已知的。

  • 函数实际上是内存中存储代码的地方。要“调用”一个函数,参数被加载到堆栈或任何其他全局内存空间中,然后跳转,即转到函数的地址。当函数完成后,它会跳转到调用它的地址(地址也存储在堆栈中。)

  • 重要的是要了解编译器以上述方式完成了翻译代码的所有艰苦工作。高级语言所具有的所有功能都只是抽象,以使您的工作更轻松。最终,它是只是位和字节,0 和 1,5 伏和零伏。

更重要的是,现代架构不允许操作系统自己做所有这些事情。大部分的内务处理也在硬件级别发生,例如内存管理,标记什么内存地址用于什么目的等。

于 2012-04-24T16:29:31.860 回答
2

它没有。相同的位序列可以解释为数字、字符串、代码、结构等等。计算机无法知道一堆比特的意图是什么。

试试这个:

int main() {
    int A = 0;
    char* pC = (char*)&S;
}

你会发现它有效。它需要整数内存并说我想把它当作一个字符数组。计算机会很高兴地接受这一点。它很少有用,但可以做到。

不同类型的唯一不同之处在于它们的处理方式。浮点数的处理方式不同于整数的处理方式与字符串的处理方式不同。如果您查看程序的低级版本,您会发现每个操作都包含特定于某种类型的数据。区别不在于位,而在于程序如何对位进行操作。

于 2012-04-24T16:28:00.567 回答
2

电脑不知道,电脑也不在乎。它所做的只是按照说明进行操作。一条这样的指令可能会说:“从该地址获取 32 位,从该地址获取另外 32 位;使用称为‘二进制补码加法’的方法组合这两个 32 位字符串;并将结果存储在第一个 32 位中提到的地址”。每条指令都指定:

  • 从中读取数据和写入数据的地址

  • 要读取或写入的位数

  • 对读取的位执行的操作

计算机并不关心操作是做什么的。只是计算机设计师足够优秀,可以使操作对我们人类有用。

像你给出的这样一个程序在一个非常真实的意义上是高水平的。需要翻译才能产生计算机可以理解的形式。这样的翻译器知道什么int是,什么int *是,并且知道它们在内存中占用了多少位以及哪些计算机操作可以有效地应用于它们。

因此,您几乎回答了自己的问题:

首先,您可能会说计算机有它的地址,好吧,当然。但是结局呢?

如果您知道开始和长度,则知道结束。

更复杂的数据结构通常由单独的、更简单的部分组成。因此,在翻译此类代码时,您获取这些部分,为它们分配偏移量,确保没有部分与另一个部分重叠,然后使用偏移量来计算用于访问这些部分的地址。

过程和功能太复杂,这里就不一一解释了。

但最后是关于您的示例程序的简短说明。正如你所说,它没有任何作用。一个聪明的翻译器会简单地向计算机写一条“什么都不做”的指令。不太聪明的翻译器将为您声明的每个变量分配地址,并编写两条指令:“为这么多位保留空间;然后什么都不做”(位的数量是存储每个变量所需的空间长度)。计算机在任何时候都不需要知道有关程序中变量的任何信息。

于 2012-04-25T08:32:41.623 回答
1

编译后的程序将包含机器指令,这些指令以反映高级类型的模式访问数据。大多数汇编语言都有不同的指令来加载和操作不同大小(加载字节、字、长整数等)或类型(有符号和无符号整数、浮点数和长整数等)的数据。因为编译器在编译期间有可用的类型信息,所以它可以发出汇编指令,将内存中的数据(全都是零和一)视为具有适当的结构,方法是发出命令以一致的方式对数据进行操作与类型系统。

对于结构和函数,有许多可能的编码取决于您使用的语言。去年夏天我教了一门编译器课程,我们花了两堂关于函数和对象布局的课。第一讲和第二讲幻灯片可在前面的链接中找到。

希望这可以帮助!

于 2012-04-24T16:26:45.683 回答
0

用高级语言编写语言规则,编译器将该信息嵌入到创建的程序中。cpu/处理器可能不太关心它只是位,它们除了在执行指令的很短的时间内没有任何意义。对于加法指令,位是加法或结果的操作数,对于加载或存储,它们可能是地址或地址的偏移量等,但在返回为无意义的位之后立即。

正如另一篇文章所述,您正在阅读的这些单词只是字母表中的字母组合,一次没有任何意义,对网络浏览器或显示像素的视频卡没有意义,但对于高级用户来说,它们确实有意义。与程序相同,缩小一点,将程序视为一个整体,您会看到指令和位的组合形成了实现变量类型的程序序列以及您编写和编译的高级程序序列。

它没有魔法

于 2012-04-24T22:01:34.257 回答