【问题标题】:Does null pointer in a struct occupy more memory than no pointer at all?结构中的空指针是否比没有指针占用更多的内存?
【发布时间】:2020-07-28 14:09:01
【问题描述】:

我正在尝试制作一个小型文本编辑器并且高效(空间/时间方面)。我还想保存对文本的更改;我会将更改和正文保存在两个列表中,两个列表都由这样的节点组成:

struct node{
    int startingLine;
    int endingLine;
    char *line;  
    char *newLine;
};

我的想法是将此结构用于 text 列表和 changes 列表;@987654322 @ 和 newLine 指向 char 数组(文本行)

当这些是 text 节点时,newLine 数组为空或指向 null,并且当行发生更改时,此节点只是移动到 更改列表,newLine 数组被替换为文本中第一行的新行填充;

这样我就不必free text 列表中的节点和malloc 更改中的另一个节点 列出并复制所有信息;但是:

  • 当我尝试将数组设置为NULL 时,我得到一个错误;我想知道为什么,我认为数组名称只是指针?

  • 另外,要使用我只知道malloc(sizeof(struct node)) 的堆,它是否也为第二个指针分配空间,即使我不立即需要它?

所以最后我问这是否是一个好主意或如何解决它或者是否可以以某种方式完善它;也许在分配节点后我应该立即将newLine 设置为NULLNULL 指针根本不占用内存,或者与不在结构中放置任何指针相比仍然占用一些内存?因为据说这个想法是让 text 列表由节点组成,但所有“无用的”newLine 指针都挂在那里。

【问题讨论】:

  • 数组和指针完全不同
  • 数组是一块内存。 malloc(sizeof(struct node)), does it allocate space for the second pointer 你是什么malloc ...即使答案很可能是noA NULL pointer occupies no memory 除非它保存在内存中占用指针大小(通常为 32 或 64 位),否则您可能会混淆指针及其指向的内容
  • 不,malloc 只为struct 及其包含的指针成员分配内存——而不是它们可能指向的内容,因为malloc 无法知道这一点。在您设置它们之前,这些指针值将是不确定的。
  • 所有char * 值的大小相同。不要混淆指针的大小和它所指向的事物的大小。
  • 数组名称在某种意义上“像指针”,但它们是常量。分配array = NULL 就像分配5 = 0

标签: c pointers memory-management struct null


【解决方案1】:

当我尝试将数组设置为 NULL 时,我得到一个错误;我想知道为什么,我认为数组名称只是指针?

否。 数组变量类似于指针,可以转换为指针,但类型不同。有关此问题的更完整答案,请参阅 Is an array name a pointer?

另外,要使用我只知道 malloc(sizeof(struct node)) 的堆,它是否也为第二个指针分配空间,即使我不立即需要它?

当您分配node 时,第二个指针是该结构的一部分,因此指针本身存在。但是malloc() 不知道node 中的指针应该指向什么,并且它不会分配linenewLine 指向的内存。

我问这是一个好主意还是如何解决它或者是否可以以某种方式完善它;也许在分配节点后我应该立即将 newLine 设置为 NULL?

如果您的node 结构中的字段是您所需要的,那就没问题了。在创建新的node 时将linenewLine 设置为nil 是个好主意,这样您就不会意外取消引用垃圾指针。

与不将任何指针放在结构中相比,NULL 指针根本不占用内存或仍然占用一些内存?

指针本身是node 结构的一部分,因此占用的内存与任何两个指针一样多。 linenewLine 指向的东西可以根据需要使用尽可能多的内存。如果linenewLine 为nil,那么它们不指向任何东西,当然也不使用内存。您可能有一千个指针都指向同一个内存块,所需的空间仍然只是该块的大小和指针本身占用的空间。尝试区分只是一个地址的指针和该地址处的数据;它们是完全不同的东西。

所以关于效率,这可以很好地避免创建新节点并复制所有数据,因为我希望仅分配指针本身占用的空间很少?

是的,在 64 位系统上,指针通常只占用 8 个字节,所以不会很多。但是您仍然必须为实际数据分配空间,因此您的方法在空间方面是否比其他方法更有效并不明显。

一开始可能很难掌握指针的窍门。获得它的最好方法是花很多时间在指针上。我建议你做一些练习来练习,例如创建一个程序,将一些输入文本分解为单词的链接列表,然后对列表进行排序。当您对指针的理解不稳定时,尝试编写一个操作数据块的文本编辑器,这会让自己陷入一个痛苦的世界;你花在用指针建立信心上的时间会得到一百倍的回报。

【讨论】:

  • 那么关于效率,这可以避免创建新节点和复制所有数据,因为我希望仅分配指针本身占用的空间很少?
  • No. An array variable is similar to a pointer, and convertible to a pointer, but it's a different type 这是错误的:数组是连续的内存块。它的名称衰减为指针,它的类型实际上与指向数组元素的指针的类型相同
  • @P__J__ 如果一个数组转换衰减为指针,它衰减什么?当然,数组和指针是相关的,但数组不仅仅是“指针”。我链接到一个更全面的问题部分是为了避免围绕这个问题经常发生的语义辩论,因此 OP 和其他人如果有兴趣可以更深入地挖掘。如果 OP 提供了遇到的特定错误,我们可能有一个很好的例子来说明数组和指针之间的特定差异,这首先激发了这个问题。
【解决方案2】:

当我尝试将数组设置为 NULL 时,我得到一个错误;我想知道为什么,我认为数组名称只是指针?

没有。除非它是 sizeof 或一元 & 运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则 表达式 类型为“@ 的 N 元素数组” 987654323@”将转换(“衰减”)为“指向T”的类型的表达式,表达式的值将是数组第一个元素的地址。否则,数组和指针是完全不同的动物。

当你声明一个数组时

int a[10];

你在记忆中得到的是

+---+
|   | a[0]
+---+
|   | a[1]
+---+
 ...
+---+
|   | a[9]
+---+

就是这样。没有单独的指针对象存储第一个元素的地址。没有与数组元素本身分开的a 对象。它只是一个元素序列。在翻译过程中,任何不是sizeof 或一元& 操作数的表达式a 实例都将替换为a[0] 的地址。

另外,要使用我只知道 malloc(sizeof(struct node)) 的堆,它是否也为第二个指针分配空间,即使我不立即需要它?

它将为linenewLine 指针成员分配空间,是的;它不会为它们分配任何额外的内存来指向。这必须作为一个单独的步骤来完成,例如

struct node *n = malloc( sizeof *n );
if ( n )
{
  n->line = malloc( line_length + 1 ); // sizeof (char) is 1 by definition so we don't need a sizeof here, +1 to account for string terminator;
  ...
}

这意味着您必须先致电free( n->line ),然后再致电free( n )

与未在结构中放置任何指针相比,NULL 指针根本不占用内存或仍然占用一些内存?

一个指针object不管它的值是否为NULL,占用的空间都是一样的。就像int 占用相同数量的空间,无论它的值是0165535 还是2147483647

指针类型的确切大小取决于平台和指针类型本身。 C 不需要指针类型的特定大小,也不需要所有指针类型的大小相同。唯一的要求是

  • void *char * 具有相同的大小和对齐方式;
  • 指向合格类型的指针与它们的不合格类型具有相同的大小和对齐方式(即,const int *volatile int *int * 应该具有相同的大小);
  • 指向所有struct 类型的指针具有相同的大小和对齐方式;
  • 指向所有union 类型的指针具有相同的大小和对齐方式;

在大多数现代通用平台(如 x86 和 x86-64)上,所有指针类型都将具有相同的大小。不过,在某些嵌入式或专用架构上可能并非如此。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-16
    • 2014-06-29
    • 1970-01-01
    • 1970-01-01
    • 2018-05-16
    • 1970-01-01
    • 2011-02-04
    相关资源
    最近更新 更多