提问人:Thibault de Villèle 提问时间:12/6/2018 最后编辑:Thibault de Villèle 更新时间:12/7/2018 访问量:169
当你在 C 语言的结构体中有一个数组时,最好的做法是什么?
What's the best practice when you have an array in a struct in C?
问:
我有一个自定义结构,我将使用它通过 TCP 连接发送数据。在这个结构中声明数组的最佳方法是什么?会不会是:
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
send(2)
编辑:由于从我的代码中复制粘贴而导致的一些不连贯性
答:
最佳做法是让项目的要求决定使用哪种方法。两者都具有明显的优势,具体取决于需要什么。
举两个例子:
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 是必需的,因为使用了指针。实施的额外严格性在提高所发送内容的可预测性方面带来了好处。
评论
send(2)
TCP
send()
send
不是用于传输复合数据结构的服务,包括解释指针和连接数据的含义。它是一种用于发送原始字节的服务。使用 时,必须将数据转换为可发送的原始字节。接收方必须从这些字节构建自己的数据结构。这意味着您必须创建一个使用字节表示数据的方案。send
当一个结构的原始字节被发送到另一个系统,并且接收系统使用这些相同的原始字节来表示一个结构时,数据的最终含义可能会有所不同,原因包括:
- 系统以不同顺序表示具有字节的对象(例如整数)。
- 系统在结构中插入不同数量的填充字节,以保持硬件要求或首选的对齐方式。
- 系统对字符或浮点数据使用不同的编码。
- 系统上的类型是不同的,因为一个可能使用两个字节,而另一个使用四个字节。
int
- 一个系统上的指针在另一个系统上毫无意义,因为它们指向从未传输到另一个系统的数据,并且包含与另一个系统上的地址布局无关的地址。
使用简单的数据结构,可以定义传输原始字节的协议,以发送表示数据结构的实际字节。如果发送和接收系统使用相同的硬件和软件,则尤其如此。但是,即使在这种情况下,也应明确指定协议:每个元素有多大,使用什么数据编码,每个元素中的字节顺序如何,等等。
假设你有简单的数据结构,并使用一个简单的协议来发送表示数据的实际字节,那么当然,在结构中声明一个数组是最简单的。如果阵列很小或通常接近满,因此通过存储和传输未使用的数据只会产生少量的浪费,那么在结构内部声明阵列可能是一个很好的解决方案。
如果阵列中所需的数据量变化不大,则通常首选动态分配阵列,以考虑资源效率。如问题所示,该结构可能包含一个指针,该指针填充了数组数据的地址。
当结构包含此类指针时,不能发送指针(如果不做出额外的努力来提供其解释)。相反,您需要使用一个或多个调用来发送结构中的其他数据,然后需要另一个调用来发送数组中的数据。当然,用于传输数据的协议必须包括一种通信所发送的数组元素数量的方法。send
send
send
还有一种选择既混合了数组的动态空间分配,又将数组包含在结构中:结构的最后一个元素可以是灵活的数组成员。这是一个在结构中声明为的数组。它必须是结构的最后一个元素。它没有固有大小,但是,在为结构分配空间时,您将为数组添加额外的空间。在这种情况下,数组不是具有指向数组的指针的结构,而是遵循内存中结构的基本部分。这种结构及其数组可以在单个调用中发送,前提是提供了上述注意事项:接收系统必须能够正确解释字节,并且必须传达数组的大小。Type dataArray[];
send
评论
struct
TCP
int* dataArray[5];
int dataArray[5];
int
data->
data
send()
size
send()