我曾多次看到内存位置的表示法,它被描绘成矩形框的线性阵列,其左侧是各自的内存地址。现在,这些地址通常写为 2000、2004、2008...等(我想是针对 32 位机器的)。
根据上述系统,内存位置只是普通的整数。但是当我用 C/C++ 打印出地址时,它们会显示为字母数字字符串。另外,如果它们实际上只是整数,那会不会有点问题,因为包含 2000 这样的数值的寄存器(例如 R1)可能突然通过将其括在括号中来充当指向内存位置的指针?像这样:(R1)->这将指向内存位置 2000
(顺便说一下,那是汇编语言)
那么内存地址在内存中究竟是如何存储的呢?
答案1
根据所述系统,内存位置只是普通的整数。
是的,因为它们只是数字。
但是当我用 C/C++ 打印出地址时,它们显示为字母数字字符串。
您没有提到这些地址是以什么基数(或数字基数)显示的。
如果地址以 2 为基数,那么就只有 0 和 1。
过去八进制表示很常见,因此地址可以用数字 0 到 7 表示。
如果地址以 16 为基数,那么十六进制数字包括 0 到 9 以及字母 A 到 F。这是“字母数字字符串”你指的是?
另外,如果它们实际上只是整数,那会不会有点问题,因为一个包含数值(如 2000)的寄存器(例如 R1)只需将其括在括号中,就可以突然充当指向内存位置的指针?像这样:(R1)->这将指向内存位置 2000
错误地编写指令或语句(又称错误)在编程中始终是一个问题。
但内存地址就像整数一样。
这就是指针算法和表/结构位移计算的实现方式。
高级编程语言(例如 C)将具有不同的变量类型以区分 apointer
和 anunsigned int
或unsigned long
,但当数据类型具有相同的存储大小时,二进制结构实际上没有区别。使用和转换的限制仅仅是为了实现编程顺序并避免潜在的错误。
在 CPU 级别,任何pointer
(或内存地址)都可以被视为整数,任何整数都可以被视为内存地址。它们都只是数字。
底线:CPU 只知道如何处理数字。为了让计算机处理此类“信息”,必须将所有东西都转换成(二进制)数字。
那么内存地址在内存中究竟是如何存储的呢?
A“内存地址”,又称指针,存储为数值,就像整数一样(具有适当的大小)。
您认为内存地址不是数字/整数的前提完全是错误的。
答案2
根据所述系统,内存位置只是普通的整数。但是当我用 C/C++ 打印出地址时,它们会显示为字母数字字符串。
可能是因为您%X
在格式字符串中使用了类似的东西,将其呈现为十六进制数。使用%d
将以十进制打印地址。
另外,如果它们实际上只是整数,那会不会有点问题,因为一个包含数值(如 2000)的寄存器(例如 R1)只需将其括在括号中,就可以突然充当指向内存位置的指针?像这样:(R1)->这将指向内存位置 2000
没错。在 C 语言中,没有什么可以阻止这种误用。管理这种情况是程序员的责任。
(顺便说一下,那是汇编语言。)那么内存地址究竟是如何存储在内存中的呢?
在现代系统中,内存地址通常是“虚拟的”,主要由专用于此任务的硬件组件 MMU(内存管理单元)管理。
答案3
内存地址可以是绝对地址,也可以是相对于基地址的偏移量。
程序中的内存地址以十六进制格式表示,通过变量名或标签等。在汇编中,地址可以存储在寄存器中,因此可以将其称为寄存器的内容,例如,(R1)是存储在寄存器 1 中的地址。检查一下:https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture#Segment_Registers。
区分实际地址和一个虚拟内存地址、分页的概念以及在特定的体系结构中操作系统的系统调用如何进行内存管理工作。
还需要知道内存分段,以及不同的段类型、共享内存的概念、动态与静态链接库等等。
根据体系结构,内存位置的长度和数据类型(我们称之为指针) 会有所不同。
最后,有些情况下实际内存空间大于总线地址指令可以寻址的空间,需要切换内存“组”,这就是为什么引入远指针的概念。参见近指针和远指针之间的区别。
简而言之,这个问题的表述太开放了。