什么是在C中转换字节顺序的可移植方式

Der*_*ick 2 c string portability network-programming endianness

我正在尝试编写服务器,它将与任何可以建立套接字连接的标准客户端进行通信(例如telnet客户端)

它最初是一个echo服务器,当然不需要担心网络字节排序.

我熟悉ntohs,ntohl,htons,htonl函数.如果我传输的是16位或32位的整数,或者发送的字符串中的字符是2或4字节的倍数,那么它们本身就很棒.

我想创建一个对字符串进行操作的函数,例如:

str_ntoh(char* net_str, char* host_str, int len)
{
    uint32_t* netp, hostp;
    netp = (uint32_t*)&net_str;
    for(i=0; i < len/4; i++){
         hostp[i] = ntoh(netp[i]);
    }
}
Run Code Online (Sandbox Code Playgroud)

或类似的东西.上面的假设是单词大小为32位.我们不能确定发送机器上的字数不是16位还是64位正确?

对于客户端程序,例如telnet,它们必须在发送之前使用hton*,在接收数据后使用ntoh*,对吗?

编辑:对于那些人,因为1-char是一个字节,字节序无关紧要:

int main(void)
{
    uint32_t a = 0x01020304;
    char* c = (char*)&a;
printf("%x %x %x %x\n", c[0], c[1], c[2], c[3]);

}
Run Code Online (Sandbox Code Playgroud)

运行此代码段.我的输出如下:

$ ./a.out
  4 3 2 1
Run Code Online (Sandbox Code Playgroud)

那些关于powerPC芯片组的人应该得到'1 2 3 4'但我们这些关于intel芯片组的人应该看看我上面得到的东西.

Tho*_*thy 17

也许我在这里遗漏了一些东西,但是你在发送字符串,即字符序列?那你就不用担心字节顺序了.这仅适用于整数中的位模式.字符串中的字符始终采用"正确"的顺序.

编辑:

Derrick,为了解决您的代码示例,我在Intel i7(little-endian)和旧的Sun Sparc(big-endian)上运行了以下(略微扩展)的程序版本

#include <stdio.h>
#include <stdint.h> 

int main(void)
{
    uint32_t a = 0x01020304;
    char* c = (char*)&a;
    char d[] = { 1, 2, 3, 4 };
    printf("The integer: %x %x %x %x\n", c[0], c[1], c[2], c[3]);
    printf("The string:  %x %x %x %x\n", d[0], d[1], d[2], d[3]);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我已经为您打印的整数添加了一个真正的char数组.

小端英特尔i7的输出:

The integer: 4 3 2 1
The string:  1 2 3 4
Run Code Online (Sandbox Code Playgroud)

并且来自big-endian Sun的输出:

The integer: 1 2 3 4
The string:  1 2 3 4
Run Code Online (Sandbox Code Playgroud)

您的多字节整数确实以不同的字节顺序存储在两台机器上,但char数组中的字符具有相同的顺序.

  • @Derrick:不,那是错的.对于字符串,第一个字符将始终位于第一个位置,依此类推.它不像多字节整数. (9认同)
  • @Derek - 这是一个32位整数,而不是一个字节数组.如果你声明:char a [] = {1,2,3,4}; 它总是以相同的顺序. (9认同)
  • @Derrick:说明托马斯的观点...假设你有一个整数数组,{0xaabb,0xccdd}.将其转换为不同的字节顺序,整数内的字节顺序将变为0xbbaa,0xddcc.但是,数组中整数的顺序不会改变.所以它是{0xbbaa,0xddcc}而不是{0xddcc,0xbbaa}.现在假设这些是8位整数而不是16.如果你有一个数组{0xaa,0xbb,0xcc,0xdd},在一个数组元素(0xaa)中没有要交换的字节,它是一个字节.并且您不会交换单个字节,因为这会更改数组的顺序. (2认同)