我有一个自定义结构,将用于通过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()
的第一种方法,但是不认为数组的内容实际上会传递给连接另一端的客户端,因为{{1 }}实际上是指向服务器内存中内存地址的指针。还是dataArray
实际上会随它一起发送数组的内容?
edit:由于我的代码中的复制粘贴而导致的一些不连贯性
答案 0 :(得分:3)
send
不是用于传输复合数据结构的服务,包括解释指针和连接的数据的含义。它是用于发送原始字节的服务。使用send
时,必须将数据转换为可以发送的原始字节。接收者必须根据这些字节构造自己的数据结构。这意味着您必须创建一种使用字节表示数据的方案。
当将结构的原始字节发送到另一个系统,并且接收系统使用这些相同的原始字节来表示结构时,由于以下原因,数据的最终含义可能会有所不同:
int
使用两个字节,而另一个则使用四个字节。使用简单的数据结构,可以定义用于传输原始字节以发送代表数据结构的实际字节的协议。如果发送和接收系统使用相同的硬件和软件,则尤其如此。但是,即使在这种情况下,也应明确指定协议:每个元素有多大,使用什么数据编码,每个元素中的字节按什么顺序等等。
假设您具有简单的数据结构,并使用简单的协议发送代表数据的实际字节,那么,当然,声明结构内部的数组是最简单的。如果数组很小或通常接近满,那么通过存储和传输未使用的数据将仅产生少量浪费,那么在结构内部声明数组可能是一个很好的解决方案。
如果阵列中所需的数据量变化不大,那么出于资源效率的考虑,通常最好动态分配阵列。如您的问题所示,该结构可能包含一个指针,该指针填充有数组数据的地址。
当一个结构包含这样的指针时,您不能使用send
发送该指针(不付出额外的努力来提供其解释)。相反,您将需要使用一个或多个send
调用来发送结构中的其他数据,然后您将需要另一个send
调用来发送数组中的数据。而且,当然,您用于传输数据的协议必须包括一种方法来传达要发送的数组元素的数量。
另一个选择是混合动态分配数组空间和将数组包括在结构中:结构的最后一个元素可以是灵活的数组成员。这是在结构内声明为Type dataArray[];
的数组。它必须是结构的最后一个元素。它没有内部大小,但是在为结构分配空间时,您将为数组添加额外的空间。在这种情况下,代替具有指向数组的指针的结构,该数组跟随内存中结构的基础部分。可以在单个send
调用中发送带有数组的这种结构,前提是要提供上述注意事项:接收系统必须能够正确解释字节,并且数组的大小必须进行通信。 / p>
答案 1 :(得分:1)
最佳实践是让项目的需求确定使用哪种方法。两者都有明显的优势,具体取决于所需的内容。
给出您的两个示例:
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的所有内容在使用完毕后都可以释放。
建议使用Serialization, and de-serialization 传输任一种格式。 (并且使用了选项2,因为使用了指针。)实施的额外严格性带来了好处,即可以提高发送内容的可预测性。