反向C结构的字节序 [英] Reverse the Endianness of a C structure

查看:169
本文介绍了反向C结构的字节序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在C结构是这样的:

typedef u_int8_t NN;
typedef u_int8_t X;
typedef int16_t S;
typedef u_int16_t U;
typedef char C;

typedef struct{
 X test;
 NN test2[2];
 C test3[4];
 U test4;
} Test;

我已经宣布的结构和编写值的字段如下:

I have declared the structure and written values to the fields as follows:

Test t;
int t_buflen = sizeof(t);
memset( &t, 0, t_buflen);
t.test = 0xde;
t.test2[0]=0xad; t.test2[1]=0x00;
t.test3[0]=0xbe; t.test3[1]=0xef; t.test3[2]=0x00; t.test3[3]=0xde;
t.test4=0xdeca; 

我送通过UDP这种结构的服务器。在present当我在本地测试这个工作得很好,但我现在需要从我的小尾数机发送这个结构向大端尾数机。我真的不知道如何做到这一点。

I am sending this structure via UDP to a server. At present this works fine when I test locally, however I now need to send this structure from my little-endian machine to a big-endian machine. I'm not really sure how to do this.

我看着使用 htons ,但我不知道是否如此,因为它似乎只为定义符号是适用于这一情况整数 16位或32位,如果我理解正确的。

I've looked into using htons but I'm not sure if that's applicable in this situation as it seem to only be defined for unsigned ints of 16 or 32 bits, if I understood correctly.

推荐答案

我想可能有两个问题在这里取决于你如何通过TCP发送此数据。

I think there may be two issues here depending on how you're sending this data over TCP.

至于,你说的字节顺序是一个问题。你当你提到使用 htons ntohs和的短裤是正确的。您也可以找到 htonl 及其相反有用的。

As, you've said endianness is an issue. You're right when you mention using htons and ntohs for shorts. You may also find htonl and its opposite useful too.

端序具有多个字节的数据类型的存储器中的字节顺序的事情。因此,对于单字节宽度的数据类型,你不必担心。你的情况是是,我猜你质疑2个字节的数据。

Endianness has to do with the byte ordering of multiple-byte data types in memory. Therefore, for single byte-width data types you do not have to worry. In your case is is the 2-byte data that I guess you're questioning.

要使用这些功能,您将需要做类似如下...

To use these functions you will need to do something like the following...

Sender:
-------
t.test     = 0xde; // Does not need to be swapped
t.test2[0] = 0xad; ... // Does not need to be swapped
t.test3[0] = 0xbe; ... // Does not need to be swapped
t.test4    = htons(0xdeca); // Needs to be swapped 

...

sendto(..., &t, ...);


Receiver:
---------
recvfrom(..., &t, ...);
t.test4    = ntohs(0xdeca); // Needs to be swapped 

使用 htons() ntohs和()使用以太网字节顺序...大端。因此,你的小端机字节互换 t.test4 并在收到大端机只使用读取值( ntohs和()是一个有效的空指令)。

Using htons() and ntohs() use the Ethernet byte ordering... big endian. Therefore your little-endian machine byte swaps t.test4 and on receipt the big-endian machine just uses that value read (ntohs() is a noop effectively).

下图将使这一更清晰......

The following diagram will make this more clear...

如果你不想使用 htons()函数及其变种,那么你可以只在字节级定义缓冲格式。此图化妆的这种更清晰......

If you did not want to use the htons() function and its variants then you could just define the buffer format at the byte level. This diagram make's this more clear...

在这种情况下,您的code可能看起来像

In this case your code might look something like

Sender:
-------
uint8_t buffer[SOME SIZE];
t.test     = 0xde;
t.test2[0] = 0xad; ... 
t.test3[0] = 0xbe; ... 
t.test4    = 0xdeca;

buffer[0] = t.test;
buffer[1] = t.test2[0];
/// and so on, until...
buffer[7] = t.test4 & 0xff;
buffer[8] = (t.test4 >> 8) & 0xff;    

...

sendto(..., buffer, ...);

Receiver:
---------
uint8_t buffer[SOME SIZE];
recvfrom(..., buffer, ...);

t.test     = buffer[0];
t.test2[0] = buffer[1];
// and so on, until...
t.test4    = buffer[7] | (buffer[8] << 8);

发送和接收code,因为缓冲区的字节布局定义,并在两台机器上运行的程序称为将工作无关的发送者和接收者各自的字节序。

The send and receive code will work regardless of the respective endianness of the sender and receiver because the byte-layout of the buffer is defined and known by the program running on both machines.

不过,如果你通过这种方式插座发送您的结构,你也应该注意下面的警告...

However, if you're sending your structure through the socket in this way you should also note the caveat below...

文章 数据对齐:振作起来,飞右 是这一个伟大的阅读...

The article "Data alignment: Straighten up and fly right" is a great read for this one...

你可能有另一个问题是数据对齐。这并非总是如此,即使使用不同端约定机器之间,但仍然是东西提防...

The other problem you might have is data alignment. This is not always the case, even between machines that use different endian conventions, but is nevertheless something to watch out for...

struct
{
    uint8_t  v1;
    uint16_t v2; 
}

在code从结构开始的偏移 V2 的上述位可以是1个字节,2个字节,4个字节(或几乎任何)。编译器不能重新排序在你的结构成员,但它可以垫变量之间的距离。

In the above bit of code the offset of v2 from the start of the structure could be 1 byte, 2 bytes, 4 bytes (or just about anything). The compiler cannot re-order members in your structure, but it can pad the distance between variables.

可以说机1有一个16位宽的数据总线。如果我们把结构不填充机将不得不做两次存取以获得 V2 。为什么?因为我们访问2个字节的存储器,一次在H / W的水平。因此编译器可以垫出像这样的结构

Lets say machine 1 has a 16-bit wide data bus. If we took the structure without padding the machine will have to do two fetches to get v2. Why? Because we access 2 bytes of memory at a time at the h/w level. Therefore the compiler could pad out the structure like so

struct
{
    uint8_t  v1;
    uint8_t  invisible_padding_created_by_compiler;
    uint16_t v2; 
}

如果发送者和接收者他们如何打包成数据结构然后只需发送结构作为二进制数据将导致您的问题有所不同。在这种情况下,你可能不得不变量打包成字节流/发送前手动缓存。这往往是最安全的方法。

If the sender and receiver differ on how they pack data into a structure then just sending the structure as a binary blob will cause you problems. In this case you may have to pack the variables into a byte stream/buffer manually before sending. This is often the safest way.

这篇关于反向C结构的字节序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆