【发布时间】:2012-03-01 07:47:55
【问题描述】:
我对@987654321@问题的答案之一有疑问。
答案是:
如果 32 位处理器可以寻址 2^32 个内存位置,那么简单 意味着该架构上的 C 指针可以引用 2^32 - 1 位置加 NULL
不是 2^32 加上 NULL 吗?为什么是-1?
编辑:抱歉不清楚。已编辑的问题。
【问题讨论】:
标签: c
我对@987654321@问题的答案之一有疑问。
答案是:
如果 32 位处理器可以寻址 2^32 个内存位置,那么简单 意味着该架构上的 C 指针可以引用 2^32 - 1 位置加 NULL
不是 2^32 加上 NULL 吗?为什么是-1?
编辑:抱歉不清楚。已编辑的问题。
【问题讨论】:
标签: c
2^32 - 1 个位置加上 NULL
等于 2^32。
在大多数编程语言和操作系统中,NULL 是一个专用指针值(通常为 0),表示无效指针,这就是为什么它不能用于指向有效内存位置的原因。
因为指针就像任何整数一样,除了使用专用值之外,没有其他方法可以指示无效指针。因为 32 位整数可以有 2^32 个可能的值,如果不计算这个 NULL 值,就会得到 2^32-1 个有效内存位置。
【讨论】:
该文本的作者将 NULL 区分为不是内存位置。因此,您将 2^32 可用值之一用于 NULL,从而使 2^32-1 可用于内存位置。
【讨论】:
NULL其实是一个值,通常是0,所以加起来就是2^32
【讨论】:
我相信 NULL 的概念最初来自内存分配器在分配内存槽时失败。通过将返回值与 NULL 进行比较,程序员可以确定指针是否可以这样使用。我不认为 NULL 在讨论中占有一席之地,它只是位置 0 (0x00000000) 的一种别名形式。
在实模式(缺少内存保护方案)系统中,位置 0 的内存通常可以被读取,有时也可以被写入(如果它不是只读的)。这当然取决于物理内存芯片是否实际连接到该位置。在许多具有可写 0 位置的实模式系统中,如果您操纵该位置,则会得到有趣的结果。在 x86(16 位实模式)PC-DOS 系统中,位置指向中断向量表中的第一个向量,该向量指向用于除以 0 的中断处理程序。程序员可能会错误地写入该处或某些有效的原因。
在保护模式系统中,访问 0 位置的程序通常会导致内存保护错误,从而终止它。我应该澄清这一点,并说应用程序的位置 0 几乎肯定不是物理位置 0,因为大多数受保护模式的操作系统已经使用主机处理器提供的虚拟寻址机制重新映射了应用程序的内存区域。在某些情况下,操作系统本身可能会授予自己或其他程序访问它喜欢的任何内存位置的权限,但这种情况很少且受到限制,以至于应用程序开发人员在他或她的一生中永远不会遇到它们。
有了这个有点冗长的背景资料,我同意那些说对于 32 位处理器通常有 2^32 个可寻址位置,范围从 0 (0x00000000) 到 2^32-1 (0xffffffff)。例外情况是实现少于 32 条寻址线的早期 32 位处理器(例如英特尔的 486sx 和摩托罗拉的 68000)。
【讨论】:
作者是说C实现必须保留处理器可以使用的地址之一,以便在C中该地址用于表示空指针。因此,C 可以比处理器少寻址一个内存位置。约定是使用地址 0 作为空指针。
实际上,一个 32 位处理器无论如何都不能真正寻址 2^32 个内存位置,因为地址空间的各个部分将被保留用于特殊目的,而不是映射到内存。
也没有实际的要求,C 实现表示使用与处理器使用相同大小的地址的指针。这样做可能效率极低,但 C 实现可以使用 33 位指针(因此需要至少 5 个字节的存储空间,并且不适合 CPU 寄存器),使其能够使用 null 值不是处理器可以处理的 2^32 个地址之一的指针。
但是假设没有这样的情况,一个 32 位指针确实可以表示 2^32 个地址中的任何一个(这些地址是否指向内存位置是另一回事),而且由于 C 需要一个空指针,一个这些地址中的一个必须用于表示“空指针”。
【讨论】: