为啥要在 C 中声明一个只包含数组的结构?

Posted

技术标签:

【中文标题】为啥要在 C 中声明一个只包含数组的结构?【英文标题】:Why declare a struct that only contains an array in C?为什么要在 C 中声明一个只包含数组的结构? 【发布时间】:2011-10-21 10:45:15 【问题描述】:

我遇到了一些包含以下内容的代码:

struct ABC 
    unsigned long array[MAX];
 abc;

什么时候使用这样的声明才有意义?

【问题讨论】:

【参考方案1】:

它允许您将数组按值传递给函数,或从函数中按值返回。

结构可以按值传递,不像数组在这些上下文中衰减为指针。

【讨论】:

谨防对不内联的函数使用超过 16 或 32 字节的数组执行此操作:通过 const-reference 传递它们更有效,除非被调用者已经需要 tmp 副本它可以摧毁。如果调用/返回没有优化掉,那么一个中到大的数组(数千字节)是通过值传递的可怕的事情。【参考方案2】:

另一个优点是它抽象了大小,因此您不必在任何声明此类对象的代码中都使用[MAX]。这也可以通过

来实现
typedef char ABC[MAX];

但是你有一个更大的问题:你必须知道ABC是一个数组类型(即使你在声明ABC类型的变量时看不到这一点)否则你会得到ABC 在函数参数列表中的含义与在变量声明/定义中的含义不同。

另一个优点是该结构允许您以后根据需要添加更多元素,而无需重写大量代码。

【讨论】:

【参考方案3】:

您可以复制结构并从函数返回结构。

你不能用数组来做到这一点 - 除非它是结构的一部分!

【讨论】:

【参考方案4】:

你可以这样复制。

struct ABC a, b;
........
a = b;

对于数组,您需要使用 memcpy 函数或循环来分配每个元素。

【讨论】:

(因此它允许更简洁的代码 - 它不会对速度等产生任何影响) 这很有用。不幸的是你不能这样做 if (a == b)!?!这是多么不一致。对于 C++,它查找 == 运算符。在 C 中它说“二进制操作数无效 ==”。【参考方案5】:

您可以使用 struct 来制作新类型的数据,例如 string。你可以定义:

struct String 
    char Char[MAX];
;

或者您可以创建一个数据列表,您可以通过函数参数使用它或在您的方法中返回它。 struct 比数组更灵活,因为它可以支持一些运算符,如 = 并且您可以在其中定义一些方法。

希望对你有用:)

【讨论】:

基本上,它是 C 最接近于创建类的东西。我喜欢这个答案,因为它最接近指出这一点。 C 中没有方法之类的东西。C 中的结构是普通的旧数据。它默认支持 = 运算符(其他答案显示这是这样做的原因),但这具有误导性,主要适用于 C++,而不是 C。 @J Sternberg:“方法”只是将子例程视为与它们影响的数据“对象”相关的一种方式。您当然可以在 C 中创建对它们进行操作的“对象”和“方法”的“类”。该语言只是没有正式定义这些东西。如果您想在 C 中创建更好的抽象,将内容填充到结构中通常是最好的方法。 此外,如果您真的想在 C 中“创建”方法,您可以使用函数指针(是的,是的,复杂的语法,无数据保护等)将函数与它们所创建的数据相关联操作。您必须在第一个参数中传入“self”(如果需要,您甚至可以将其命名为“this”),因为在 C 中的函数内部不会自动创建 this 指针。当然,这都是体操,你得到在 C++ 中默认情况下是这样的,尽管确实可能会有隐藏的开销作为奖励......【参考方案6】:

使用这样的struct 的另一个优点是它在使用这样的struct 的地方强制类型安全;特别是如果您有两种类型,由用于不同目的的相同大小的数组组成,这些类型将帮助您避免意外地不恰当地使用数组。

如果您不将数组包装在struct 中,您仍然可以为其声明typedef:这具有struct 的一些优点 – • 类型声明一次, • 大小为自动更正, • 代码的意图变得更清晰, • 代码更易于维护 - 但您失去了 ◦ 严格的类型安全性, ◦ 复制和返回类型值的能力,以及 ◦ 以后添加成员而不破坏其余部分的能力你的代码。给定类型的裸数组的两个typedefs 仅在它们具有不同大小时才会产生不同的类型。此外,如果在函数参数中使用 typedef 而不使用 *,则它等效于 char *,从而大大降低了类型安全性。

总结

typedef struct A_s_s  char m[113];  A_s_t; // Full type safey, assignable
typedef char   A_c_t[113];                   // Partial type-safety, not assignable

A_s_t          v_s(void);     // Allowed
A_c_t          v_c(void);     // Forbidden

void           s__v(A_s_t);     // Type-safe, pass by value
void           sP_v(A_s_t *);   // Type-safe
void           c__v(A_c_t);     // UNSAFE, just means char * (GRRR!)
void           cP_v(A_c_t *);   // SEMI-safe, accepts any array of 113

【讨论】:

【参考方案7】:

一个结构可以包含数组初始化、复制和fini 函数,这些函数模拟了OOP 内存管理范例的一些优点。事实上,很容易扩展这个概念来编写一个通用的内存管理实用程序(通过使用 sizeof() 结构来准确知道正在管理多少字节)来管理任何用户定义的结构。许多用 C 编写的智能生产代码库大量使用这些,并且通常从不使用数组,除非它的范围非常本地化。

事实上,对于嵌入在结构中的数组,您可以在任何时候想要访问该数组时执行其他“智能操作”,例如边界检查。同样,除非数组范围非常有限,否则使用它并在程序之间传递信息是一个坏主意。迟早,您会遇到让您彻夜难眠并破坏您的周末的错误。

【讨论】:

这并没有回答为什么人们可能会使用包含一个数组的struct

以上是关于为啥要在 C 中声明一个只包含数组的结构?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我什至应该考虑在 C++ 中使用结构? [复制]

C:为啥你可以通过值传递(给函数)一个结构,而不是一个数组?

结构指针函数中未声明的变量 c

Keil中C语言模块化编程时全局变量、结构体处理细节

为啥派生类对象的指针数组无法声明

急求c语言 dev c++) 利用结构体做一个小系统,为啥直接无法编译运行?