在linux,2.6.x上,给出以下结构
struct A
{
int a;
int b;
} ss;
将上述结构写入管道时我想到的两个选项是
一个比另一个好吗?
答案 0 :(得分:2)
没有“正确”的方式,但有些方法肯定比其他方法更好。
对于初学者来说,int的大小取决于机器,编译器和选项。您可能不希望您的network / ipc协议随之变化。其次,整数中字节的顺序可以随着相同的事情而变化。因此,首先定义整数的大小和顺序(endianess)。假设你使用32位,大端。然后使用数字/逻辑运算提取这些字节 - 而不是字节复制或叠加。最后,您可能希望在流中实际编码您的大小假设。
一些示例代码。每个函数将参数编码到提供的缓冲区中,并返回缓冲区中使用的字符数。
int encode_int(int v, unsigned char *s) {
s[0] = (v>>24) & 0xff;
s[1] = (v>>16) & 0xff;
s[2] = (v>>8) & 0xff;
s[3] = v & 0xff;
return 4;
}
int encode_A(struct A *a, unsigned char *s) {
int offset = 0;
s[offset++] = 4; // Size of ints - really belongs in a global header or in encode_int
offset += encode_int(a->a, s+offset);
offset += encode_int(a->b, s+offset);
return offset;
}
解码必须使用提供的字节并使用逻辑/算术运算重新组合整数。另一种可能性是使encode_int使用可变数量的字节(并编码它使用的数量),如果你期望大多数小整数和/或想要也处理64位平台。还有许多其他选项 - 主要的是不允许内存中表示的任意性来定义您的协议。
另请参阅ntohl,htonl,ntohs,htons标准函数。
聚苯乙烯。最后一次编辑 - 如果阅读器中整数的大小与编写器中的整数大小不同,则必须注意正确处理负整数。
答案 1 :(得分:0)
我完全同意DrC。
您的简单结构表明您只是在暗示您手头的问题。您需要考虑的是结构的内存布局,这可能会有很大的不同,具体取决于CPU,编译器及其sizeof(int)。考虑:
struct B {
int a;
char b;
int c;
}
编译器将在sizeof(int)边界上对齐'c'。也就是说'b'和'之间会有一些填充。 'C'。如果sizeof(int)是2,那么只需要一个额外的字节就可以在int边界上启动'c'。如果sizeof(int)为4,就像在大多数32位处理器上一样,则需要三个填充字节。问题确实来自64位处理器。 sizeof(int)可以是四个或八个。
因此,对问题的简单回答是分别传输结构的每个元素,因为这样可以避免传输任何填充字节。但是如果你的管道的两端都同意sizeof(< data-type>)等于什么,以及int,long,long longs,float,double,...的字节顺序,那么你只会逃避这一点。
但是考虑到目前的网络带宽,我认为最好使用基于ASCII的传输协议(例如XML),除非有一个很好的理由。