我的问题是关于 4GB 可寻址系统的内存管理
char *p = NULL;
它是否占用任何内存?
如果是这样,堆或堆栈在哪里,有多少?也说说char **p=NULL;
3 回答
在典型的 32 位系统上,它占用 4 个字节。
假设您的示例是某个函数中局部变量的定义,则这些字节是从堆栈中获取的。虽然:
- 如果变量没有在其他地方使用,编译器可能会从生成的代码中完全删除它;
- 如果该变量仅在本地使用并且不占用其地址,则可以将其放入寄存器中,因此它不会占用“常规”内存。
相反,如果它是一个全局变量(或者,一般来说,一个具有静态存储持续时间的变量),那么在大多数系统上都有一个特殊的内存区域(与堆栈和所谓的堆分开)用于它们。通常它只是在写时复制模式下直接从可执行映像映射的内存区域。所以这里的 4 个字节都在这个特定的内存区域中,在可执行文件内部的空间中。
这同样适用于char **p
,根据原则,它没有理由比 更大或不同char *
。
顺便说一句,如果char * p
或者char ** p
是聚合数据类型(通常是 a struct
)的一部分,它们占用的空间来自struct
分配的任何地方 - 如果struct
变量是局部变量,它来自堆栈,如果它是动态分配malloc
的堆,如果它是全局的,它来自全局的特殊内存区域。请记住,在谈论struct
s 占用的空间时,有关填充的其他考虑因素也会发挥作用。
请注意,所有这些都是对“典型”32 位系统有效的考虑因素;没有什么能阻止一些奇怪的建筑char **
在尺寸上有所不同char *
(尽管我认为没有任何理由这样做)。不过,您可以使用sizeof
运算符执行直接检查。
就标准而言,我认为对指针大小施加的唯一限制是任何指向数据的指针都可以在void *
不丢失信息的情况下相互转换(实际上,该标准从未提及堆栈或寄存器)。此外,请记住,只要“可观察行为”与标准要求的内容一致,编译器就可以做任何它想做的事情,因此标准规定的这些实现细节并不能真正保证,尽管有更多细节可以在您使用的编译器的文档中找到。
如果没有上下文,变量的两个版本p
通常会分别占用一个char*
和一个char**
的内存,这要么是自动(“堆栈”),要么是静态(“全局”)存储。所需的大小不大于 a 的大小void*
(通常是一个机器字)。
总是允许编译器表现得“好像”这个变量存储在内存中,但如果它可以直接替换它的值,它可能会完全删除该变量。从这个意义上说,不能绝对保证您的 C 构造会产生任何特定的具体机器代码。
指针只是一个可以保存地址的普通变量。无论在哪里char *
创建变量,它都会使用内存,无论变量的值是什么。在 32 位系统上,指针的典型大小是 32 位,在 64 位机器上是 64 位。喜欢int
或long
。