我想知道计算机以1s和0s /低电压和高电压,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的指针......现在这些将以0s和1s的形式存储在某处......那么,如何计算机是否知道从哪个位开始这样的变量以及它结束的位置?首先,你可能会说计算机有地址,好的,授予。但是结束呢?......那么像对象/结构这样复杂的数据类型呢?
最后但并非最不重要的是,功能/程序呢?
答案 0 :(得分:4)
你现在正在阅读的段落只不过是一串字母和标点符号。你怎么知道一个单词的开头和结尾?你怎么知道这些词是什么意思?这段文本如何传达有用的信息?
你可以对数学说同样的话。当你看到写在页面上的数学表达式时,它们只是一系列数字和符号,但它们是以紧凑形式传达深层思想的有力方式。然后是音乐。点流,旗帜和线条的流程如何表示像音乐一样短暂的东西?
答案当然是有规则。这些字母不仅是随机组合的 - 它们具有特定的序列。当你遵循你和我都知道的规则时,你就能够辨别出这些词,理解它们各自的含义,并将它们融入思想中。
二进制数据也是如此。区分数据和随机比特的是规则的存在,如果遵循这些规则,则允许以有意义的方式解释比特。现在,您已经提出了许多涉及各种规则的问题。试图解释它们都会占用比这个答案更合理的空间(而且比我愿意投入的时间更多)。但是,如果你拿起一本关于计算机体系结构的书,你会发现规则,它们如何工作,它们如何组织以及它们如何实现的完整讨论。这真是有趣的东西!
如果你还没有准备好深入了解实际的计算机架构,那么一本能给你很多见解的优秀书籍是Douglas Hofstadter的 Godel,Escher,Bach:A Eternal Golden Braid 。这是一本厚厚的书,思想密集。但它也写得很好而且很有趣,你不一定要从头到尾阅读它来学习很多有趣的东西。
答案 1 :(得分:3)
你可以通过尽可能接近金属来回答所有这些问题(以及许多更多关于计算机的问题):也就是说,学习汇编。我建议阅读这本书Art of Assembly(免费在线提供,也涵盖了这些主题。另外,请在Assembly learning resources上阅读我的答案。现在,让我简单回答一下你的问题:
你是对的,因为计算机只能看到无穷无尽的比特流。操作系统完成创建文件系统的工作。甚至可以认为ram是一个非常简单的文件系统(页面或段是现在这意味着操作系统有一个表,它跟踪每个程序存储的位置,数据是什么,代码是什么等。
基本级别的变量只不过是bytes.Now,当你写一个语句如
a = b + 1
编译器实际上将任意地址分配给变量和硬代码(即将实际常量,例如0xA3F0)写入每个引用它的语句。
数据结构以多种不同的方式存储。但是,当谈到c结构时,事情就更简单了:它们只是存储了这个结构一个接一个地包含的变量,如果我们忽略诸如填充之类的东西。这就是结构长度始终为人所知的原因。
函数实际上是存储代码的内存中的位置。要“调用”一个函数,将参数加载到stack或任何其他全局内存空间中,然后跳转,即转到函数的地址已经完成。当函数完成后,它会跳转到调用它的地址(地址也存储在堆栈中。)
重要的是要理解编译器会以上述方式完成翻译代码的所有艰苦工作。高级语言具有的所有功能只是抽象,以使您的工作更轻松。最后它只是位和字节,0和1,5伏和零伏。
更重要的是,现代架构不让操作系统自行完成所有这些工作。许多内务处理也发生在硬件层面,例如内存管理,标记内存地址用于什么目的等。
答案 2 :(得分:2)
没有。相同的位序列可以解释为数字,字符串,代码,结构等等。计算机无法知道一堆比特是什么意思。
试试这个:
int main() {
int A = 0;
char* pC = (char*)&S;
}
你会发现它有效。它需要整数内存,并说我想把它当作一个字符数组。电脑很乐意配合这个。它很少有用,但可以做到。
不同类型的唯一不同之处是如何对待它们。不同于整数的浮点数与字符串的处理方式不同。如果查看程序的低级版本,您会发现每个操作都包含特定于某种类型的数据。差别不在于位,而在于程序如何对位进行操作。
答案 3 :(得分:2)
电脑不知道,电脑也不在乎。它只是遵循指示。一条这样的指令可能会说:“从该地址取32位,从该地址取32位;通过使用称为'二进制补码'的方法组合这两个32位字符串;并在第一次将结果存储为32位提到地址“。每条指令都指定:
从中读取数据的地址以及要写入的数据
读取或写入的位数
要对读取的位执行的操作
计算机不关心操作的作用。只是计算机设计师足够好,使操作对我们人类有用。
你提供的程序在高级中非常真实。它需要翻译才能生成计算机可以理解的表格。这样的翻译器知道int
是什么,int *
是什么,并且知道他们在内存中占用了多少比特以及哪些计算机操作可以有效地应用于它们。
因此,你几乎回答了自己的问题:
首先,你可能会说计算机有地址,好的,授予。但到底怎么样?
如果您知道开始和长度,则结束。
更复杂的数据结构通常由各个更简单的部分组成。因此,在翻译此类代码时,您将获取部件,为其分配偏移量,确保没有任何部件与其他部件重叠,然后使用偏移量计算用于访问部件的地址。
程序和功能太复杂,无法在此解释。
但最后简要说明了你的示例程序。正如你所说,它什么都不做。聪明的翻译人员只需向计算机写一条“无所事事”的指令即可。一个不太聪明的翻译器将为你声明的每个变量分配地址,并写入两条指令:“为这么多位保留空间;然后什么都不做”(位数是存储每个变量所需的空间长度) )。在任何时候,计算机都不需要了解程序中的变量。
答案 4 :(得分:1)
编译的程序将包含以反映高级类型的模式访问数据的机器指令。大多数汇编语言都有不同的指令来加载和操作不同大小的数据(加载字节,单词,长整数等)或类型(有符号和无符号整数,浮点数和长整数等)。因为编译器在编译期间具有可用的类型信息,所以它可以发出汇编指令来处理内存中的数据,这些指令只是零和1,具有适当的结构,通过发出命令以一致的方式操作数据与类型系统。
对于结构和函数,根据您使用的语言,有许多可能的编码。去年夏天我教了一个编译器课程,我们花了两个关于功能和对象布局的讲座。 slides for the first和second lectures可在之前的链接中找到。
希望这有帮助!
答案 5 :(得分:0)
使用高级语言编写语言规则和编译器将该信息嵌入到创建的程序中。 cpu /处理器可能不在乎它只是比特,除了在执行指令的非常短的时间内它们没有任何意义。对于加法指令,这些位是加法或结果的操作数,对于加载或存储,它们可能是地址或地址的偏移等,但在回到无意义的位之后立即。
正如另一篇文章所提到的,你正在阅读的这些单词只是字母表中的字母组合,一次没有任何意义,对网页浏览器或显示像素的显卡没有任何意义,但是对于高级别用户,他们确实有意义。与程序相同,缩小一点,查看整个程序,您将看到指令和位的组合形成程序序列,实现变量类型和您编写和编译的高级程序序列。
它没有魔力