使用结构体数组和使用结构体指针数组有什么优缺点?

5

我正在尝试决定应该使用哪个。

我能想到指向结构体的优点有:

  • 如果您不使用数组的所有元素,则浪费的空间较少。
  • 交换数组元素时开销较小。

双方还有其他的优缺点吗?


你有什么要求?你知道编译时数组中会有多少元素吗?数组中元素的交换频率有多高?结构体的复制性能是否值得关注? - Naveen
1
这个问题太过笼统,没有实际用处。答案本质上是一整章的《学习C语言编程》。这就相当于询问购买打印机和购买显示器的利弊。它们都可以输出东西,但它们是不同的。 - Kerrek SB
@KerrekSB,询问两种情况的区别有什么问题吗?我发现这些答案很有用,希望将来有同样问题的人也能受益。 - Michael
@Michael:嗯,这是一个非常广泛的问题,因此它会比较开放式。关于这个问题有很多可以说的事情,所以不清楚完整的答案应该是什么样子的。当然,这是一个完全有效的问题,但是SO不鼓励那些引导出教程式和开放式答案的问题。 - Kerrek SB
我在思考一个项目时遇到了完全相同的问题,并找到了有用的答案。 - Rakesh Solanki
6个回答

5

这些方法还有一些其他的区别:

  • 数组指针的方法减少了调整数组大小的开销;
  • 数组指针的方法给你一个“空”/“未使用”的值(NULL)。如果在您的应用程序中语义上有效,则这是一个优点(您不必更改struct本身来表示此内容);
  • 数组指针的方法允许数组的多个元素引用相同的struct,而不是副本。同样,只有在这种情况在您的应用程序中语义上合理时才具有优势;
  • 结构体数组的方法提供更多的参考局部性(在数组中彼此靠近的struct也在内存中彼此靠近,这在某些情况下可以提高性能);
  • 对于非常大量的项目,结构体数组的方法需要一个大的连续内存块,如果您的进程地址空间变得分散,则可能无法使用。

4
使用指针数组或指针的一个缺点是:
指针(很可能)需要使用动态内存分配,这意味着需要手动管理此动态内存。
动态内存分配比堆栈分配慢一些。
此外,使用动态内存更容易出现使用错误。
话虽如此,选择哪种方式实际上取决于:
  • 您的结构有多大
  • 编译时是否已知所需结构的数量
  • 您需要多频繁地交换结构

4
下投票者:请解释你的负评或者不要滥用你的匿名负评权利。 - Alok Save
两个原因,如果你知道你在做什么,动态内存既不会更慢也不会更容易出错。静态内存和动态内存都有各自的缺陷。 - Lie Ryan
@LieRyan:动态内存比栈慢是一个被证实的事实。至于出错的可能性,我的回答说“更容易出现使用错误”,希望你能理解其中的区别。 - Alok Save
@AIs:尝试创建一个排序算法,可以比指向结构体的指针数组更快地对非平凡结构体数组进行排序。正确使用时,两者都可以比另一个更快。至于静态内存 less 错误倾向的说法是不正确的,静态内存只有自己的缺陷,例如您无法返回静态分配的对象,或者您可能会不必要地复制结构体,或者在调用函数时可能会(意外地)进行副本,因此您对对象的修改不会反映给调用者。如果您不知道何时使用其中之一,则这些都是常见错误。 - Lie Ryan

3
这里有一个重要的区别,结构体数组需要一个大小为sizeof(struct)*n的连续内存块,而指向结构体的指针数组虽然仍然需要连续的内存块来存储数组本身,但是每个结构体并不一定要相邻,因此前者将需要一个大块的内存,后者将导致更多的碎片化,这是你的选择。
此外,有人提到编写结构体数组到磁盘上会更容易,这是正确的,因为你只需要调用一次write函数,使用第一个元素的指针和sizeof(struct)*n即可,如果使用指针数组则必须循环并单独写入每个元素。
编辑:当然,对于指针数组,你需要在循环中分配每个结构体。希望这能帮助你。

2
如果你需要将数据写入磁盘、通过套接字发送或将其放置在共享内存中(这些都是嵌入式实时应用程序中非常常见的任务),那么数组可能会稍微简单一些。数组避免了使用malloc(),但它们经常需要realloc(),正如caf所指出的,如果数组很大且内存空间被分段,这可能会成为问题。当然,realloc()不适用于.bss或.text中的数组。我期待其他答案。好问题。

请记住,realloc函数适用于通过malloc分配的动态内存,而不适用于在堆栈中声明或静态分配的数组... - Jason
就像Als一样,我也刚刚收到了一个奇怪的负评。我同意这可能不是世界上最出色的答案,但拜托了... - Joseph Quinsey
@Jason:好的提醒。据我所知,无法扩展.bss,而且我希望没有人会想要一个realloca()函数! - Joseph Quinsey

1

其中一个可能的缺点是,使用指针会给你,程序员带来更多的负担。你需要决定你的项目目标。

如果你不打算做很多排序和交换操作,而且你有足够的内存并且不打算完全利用它,那么你需要问自己是否值得使用指针给自己带来的麻烦。


我猜测那个给我点踩的人认为即使我们只是处理一个包含12个元素的数组,我们也应该尽可能地采用最困难的方式来完成任务?你想详细说明一下吗? - jamesmortensen

1

指针数组需要存储指针和结构体的空间。然而,如果不同的结构体包含不同但不变的有意义数据量,使用结构体指针可以允许为它们分配不同数量的空间。在某些情况下,这种节省空间的方法可能比额外指针的成本更加划算。

使用指针数组访问结构体通常需要每次访问结构体时进行额外的表格查找步骤,而使用结构体数组则需要进行额外的乘法运算。在许多新架构中,乘法比表格查找更便宜,但在一些较小或旧的架构中则相反。此外,一些较小或旧的架构可能会对跨越某些内存边界的对象产生困难。即使在无法分配超过80字节的数组的架构上,分配一个由8个20字节结构体指针组成的数组仍然是可能的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接