【问题标题】:char *p =NULL takes memory?char *p =NULL 占用内存?
【发布时间】:2012-08-10 19:28:11
【问题描述】:

我的问题是关于 4GB 可寻址系统的内存管理
char *p = NULL;
它是否占用任何内存?
如果是这样,堆或堆栈在哪里,有多少? 也说说char **p=NULL;

【问题讨论】:

  • 您的p 声明在哪里?在函数中本地?在函数之外?
  • @AndreyT 有什么不同吗?如果是这样,请告诉我。

标签: c pointers memory heap-memory


【解决方案1】:

在典型的 32 位系统上,它占用 4 个字节。

假设您的示例是某个函数中局部变量的定义,则这些字节是从堆栈中获取的。虽然:

  • 如果该变量未在其他地方使用,编译器可能会将其从生成的代码中完全删除;
  • 如果变量只在本地使用并且不取其地址,则可以将其放入寄存器中,这样就不会占用“常规”内存。

如果相反,它是一个全局变量(或者,一般来说,是一个具有静态存储持续时间的变量),那么在大多数系统上都有一个特殊的内存区域(与堆栈和其他 -称为堆)用于它们。通常它只是在写时复制模式下直接从可执行映像映射的内存区域。所以这里的 4 个字节都被占用在这个特定的内存区域中,都在可执行文件内部的空间中。

char **p 也是如此,原则上,它没有理由比 char * 更大或有所不同。


顺便说一句,如果char * pchar ** p 是聚合数据类型(通常是struct)的一部分,那么它们占用的空间来自分配struct 的任何位置——如果struct 变量是一个局部变量,它来自堆栈,如果它是在堆上使用malloc 动态分配的,如果它是一个全局变量,它来自全局变量的特殊内存区域。请记住,在谈到 structs 占用的空间时,还有关于填充的其他考虑因素。


请注意,所有这些都是对“典型”32 位系统有效的考虑因素;没有什么能阻止一些奇怪的架构使char ** 的大小与char * 不同(尽管我认为没有任何理由这样做)。不过,您可以使用sizeof 运算符执行直接检查。

就标准而言,我认为对指针大小施加的唯一约束是任何指向数据的指针都可以在不丢失信息的情况下与void * 相互转换(实际上,标准从未提及堆栈或寄存器)。此外,请记住,只要“可观察行为”与标准要求的内容一致,编译器就可以做任何它想做的事情,因此标准规定的这些实现细节并不能真正保证,尽管有更多细节可以在您使用的编译器的文档中找到。

【讨论】:

  • 否则 - 它将位于堆栈上。 char ** p 也一样;
  • 如果它是动态分配的struct 上的成员,那么它在堆栈上吗?
  • @BinaryWorrier:它不能是动态分配的struct 的成员,因为不允许像 OP 那样直接初始化它们。
  • @BinaryWorrier 不,无论结构在哪里。但是 OP 示例中的语法甚至对结构初始化都无效,所以这有点错过了这个问题。
  • @Matteo Italia:我的 C 生锈了,所以我没有注意到这一点,但是我问了,因为它的细微差别可能会让提问者感到困惑(以下 cmets 似乎已经证明了这一点)。什么生活在什么记忆中以及事物是如何传递的,这对新手来说是无休止的困惑,即使在像 c 这样的基本语言中也是如此。类似于在 C# 世界中引起“值类型总是放在堆栈上”和“对象通过引用传递”神话的混淆。 +1 顺便说一句
【解决方案2】:

如果没有上下文,变量p 的两个版本通常会分别占用一个char* 和一个char** 的内存,这要么是自动(“堆栈”),要么是静态(“全局”)存储。所需大小不大于void* 的大小(通常是一个机器字)。

总是允许编译器表现得“好像”这个变量存储在内存中,但如果它可以直接替换它的值,它可能会完全删除该变量。从这个意义上说,不能绝对保证您的 C 构造会产生任何特定的具体机器代码。

【讨论】:

    【解决方案3】:

    指针只是一个可以保存地址的普通变量。无论在哪里创建 char * 变量,它都会使用内存,无论变量的值是什么。在 32 位系统上,指针的典型大小是 32 位,而在 64 位机器上是 64 位。喜欢intlong

    【讨论】:

      猜你喜欢
      • 2015-05-02
      • 2016-02-25
      • 2016-03-05
      • 2011-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-07
      • 2021-04-15
      相关资源
      最近更新 更多