基于ASCII表,当我们将'TAB'和十进制9存储到存储器时,它们都存储为“1001”。计算机如何知道它是'TAB'还是小数9?
答案 0 :(得分:2)
计算机无法“知道”内存中特定地址的类型,该知识会被包含在程序的指令中。
当你编写一个程序并且它看到你的变量时,编译器会创建汇编代码,在某个地方写入那段数据,并且在其他地方有一些其他代码读取内存地址,将其解释为char < / em>的。 char的知识不存储在内存中。该内存地址的位置是唯一将这两个操作联系在一起的东西。
当读取该位置时,程序集不会说“查看有哪些数据类型”,它只是说“加载此内存位置并将其视为char”。例如,如果某些东西用char以外的东西覆盖了那个内存地址,那么CPU只会将该内存加载为char,结果会发生各种奇怪的事情。
例如,在以下程序中:
#include <stdio.h>
int main()
{
int x;
x = 9;
char* y;
y = &x;
printf("\"%s\" \"%d\"\n", y, x);
printf("%p\n%p", y, &x);
return 0;
}
您将获得如下输出:
" " "9"
0x7ffd401ce68c
0x7ffd401ce68c
因此我们看到内存中的相同的位置被视为char和int。内存中的值不知道或不关心它的用途。
答案 1 :(得分:0)
让我以古老的VAX为例。假设您在某个位置定义了8个字节的内存:
location:
.ASCII /ABCDEFGH/
指令
MOVC3 location, 8, some_other_location
将内存视为字符。
指令
ADDL2 location, R0
将相同的内存视为整数值
指令
MULD2 location, R8
将相同的内存视为浮点值。
指示:
jmp location
将相同的内存视为代码(但可能会呕吐)。
记忆是记忆。如何解释它取决于对存储器进行操作的指令。计算机不知道存储在某个位置的内容。这取决于程序员的决定。
答案 2 :(得分:0)
文本数据或任何其他类型的数据本身没有区别,因此计算机无法区分内存中的ASCII字符或普通数字。
然而,作用于该数据的进程以不同方式处理不同的存储器内容,并附带烘焙到其指令序列中的数据类型的“知识”。例如,对printf()的调用要求参数为string of characters(以空值终止的字符串)。所以你拥有它,知识就在这个过程中,而不是数据。
这可能会导致问题,因为人类程序员需要确保将正确类型的参数(数据)传递给特定的函数(进程)。 - 幸运的是,编译器(以及compile time开发期间使用的其他帮助程序,或者在使用static analysis之前)也“知道”必须输入的内容(在strongly typed languages的情况下) ,这样一个错误的程序通常不会编译。 - 但是在任何情况下,例如在C中,您可以将任何内存内容视为您想要的任何类型的数据(例如,通过type casting),甚至作为可执行代码也有一些限制。
在运行时,(几乎)没有任何东西阻止程序将任意内存位置的数据解释为ASCII文本或普通数字,这只是表示问题。
但是,存在关于程序如何构造以及存储文本的位置的约定,作为在编译时已知的静态字符串,即纯文本。通常,它们被放置在程序的.data or .rodata segment中(通常不在.text段中)。您可以使用strings扫描二进制程序,如下所示:
$ strings /usr/bin/strings
或者,如果您想了解更多有关.data / .rodata细分的信息,binutils'objdump可能会派上用场:
$ objdump -h /usr/bin/strings
$ objdump --full-contents --section .rodata /usr/bin/strings
使用十六进制编辑器可以完成同样的操作:
$ xxd <my-binary>
$ xxd /usr/bin/strings
最后,单个程序可以知道如何处理其内存,以及如何解释其中的二进制数据的各个位。该程序通常在一个操作系统内运行,该操作系统定义了对可访问的内存区域以及如何访问的其他类型的限制,以及程序可能与框外部或内部的其他进程通信(访问权限,需要系统API的系统API)某些类型的数据,例如文本或二进制数据)。但同样,在这种情况下,知识也在于过程,而不在于数据本身。硬件(即处理器和内存(RAM,FLASH ...))不会从根本上区别于其他类型的数据。