繁体   English   中英

在C中的结构中有数组时的最佳实践是什么?

[英]What's the best practice when you have an array in a struct in C?

我有一个自定义结构,将用于通过TCP连接发送数据。 在此struct中声明数组的最佳方法是什么? 可不可能是 :

typedef struct programData {
    int* dataArray;
    size_t numberofelements;
} pd;
// ...
pd data = {0};
data.dataArray = malloc(5*sizeof(int));
// put content in array ...
data.numerofelements = 5;

还是这样呢:

typedef struct programData {
    int dataArray[5];
} pd;
// ...
pd data = {0};
data.dataArray[0] = ...;
// ...
data.dataArray[4] = ...;

我采取了第一种方法,是出于不在C中使用malloc()的习惯,但不认为数组的内容实际上会传递给连接另一端的客户端,因为dataArray实际上是指向a的指针。服务器内存中的内存地址。 还是send(2)实际使用它发送数组的内容?

编辑:由于从我的代码复制粘贴一些不一致性

send不是用于传输复合数据结构的服务,包括解释指针和连接的数据的含义。 它是用于发送原始字节的服务。 使用send ,必须将数据转换为可以发送的原始字节。 接收者必须根据这些字节构造自己的数据结构。 这意味着您必须创建一个方案来使用字节表示数据。

当将结构的原始字节发送到另一个系统,并且接收系统使用这些相同的原始字节来表示结构时,由于以下原因,数据的最终含义可能会有所不同:

  • 系统用字节以不同顺序表示对象(例如整数)。
  • 系统在结构中插入不同数量的填充字节,以保持硬件所需或首选的对齐方式。
  • 系统对字符或浮点数据使用不同的编码。
  • 系统上的类型不同,其中一个可以将两个字节用于int而另一个可以使用四个字节。
  • 一个系统上的指针在另一个系统上毫无意义,因为它们指向的数据从未传输到另一个系统,并且包含与另一个系统上的地址布局无关的地址。

使用简单的数据结构,可以定义用于传输原始字节以发送代表数据结构的实际字节的协议。 如果发送和接收系统使用相同的硬件和软件,则尤其如此。 但是,即使在这种情况下,也应明确规定协议:每个元素有多大,使用什么数据编码,每个元素中的字节按什么顺序等等。

假设您具有简单的数据结构,并使用简单的协议发送表示数据的实际字节,那么,当然,在结构内部声明一个数组是最简单的。 如果数组很小或通常接近满,那么通过存储和传输未使用的数据将仅产生少量浪费,那么在结构内部声明数组可能是一个很好的解决方案。

如果阵列中所需的数据量变化不大,那么从资源效率的角度来看,通常最好动态分配阵列。 如您的问题所示,该结构可能包含一个指针,该指针填充有数组数据的地址。

当结构包含这样的指针,你不能发送终场前send (不进行额外的努力,为它的解释)。 相反,您将需要使用一个或多个send调用来发送结构中的其他数据,然后,您将需要另一个send调用来发送数组中的数据。 而且,当然,您用于传输数据的协议必须包括一种方法来传达要发送的数组元素的数量。

还有一个选项既混合了为阵列动态分配空间,又将阵列包括在结构中:结构的最后一个元素可以是灵活的阵列成员。 这是在结构内声明为Type dataArray[];的数组Type dataArray[]; 它必须是结构的最后一个元素。 它没有内部大小,但是在为结构分配空间时,您将为数组添加额外的空间。 在这种情况下,代替具有指向数组的指针的结构,该数组跟随内存中结构的基础部分。 如果提供以上注意事项,则可以在单个send调用中发送带有数组的这种结构:接收系统必须能够正确解释字节,并且必须传达数组的大小。

最佳实践是让项目的需求确定使用哪种方法。 两者都有明显的优势,具体取决于所需的内容。

举两个例子:

1)

typedef struct programData {
int dataArray[5];//assuming '*' was a typo
} pd;

2)

typedef struct programData {
    int* dataArray;
    size_t numberofelements;
} pd; 

如果您在运行前知道大小要求,则始终首选方法1)(一种更简单的方法)。 如果不是,则需要选项2),但有成本。 动态分配内存会增加代码在错误处理和内存管理方面的复杂性,并确保使用calloc和family的所有内容在使用完后都可以释放。

建议使用序列化和反序列化来传输这两种形式。 (并且使用了选项2作为指针所必需的。)实施的额外严格性带来了好处,即增加了所发送内容的可预测性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM