联合体和字节序

8
typedef union status
{
    int nri;
    char cit[2];
}Status;

int main()  {
    Status s;
    s.nri = 1;
    printf("%d \n",s.nri);
    printf("%d,%d,\n",s.cit[0],s.cit[1]);
}

输出:

1
0,1

我知道第二行输出的结果取决于CPU的字节序。那么在编写跨平台程序时,如何处理这个问题呢?有没有什么方法可以检查CPU的字节序呢?


你尝试达成什么目标? - This isn't my real name
根据大小端,第二行输出会改变,对吗?我想编写一个与平台无关的代码。 - Vallabh Patade
3个回答

4
您可以使用 htonl() 和 / 或 ntohl()htonl() 代表 "主机到网络长整数",而 ntohl() 代表 "网络到主机长整数"。 "主机" 和 "网络" 指的是字节顺序。 网络字节顺序是 "大端序(big-endian)"。 如果主机平台也是 "大端序(big-endian)",则这些操作将不起作用。 使用这些例程,以下程序始终将报告相同的输出:
uint32_t x = htonl(1);
unsigned char *p = (void *)&x;
printf("%u %u %u %u\n", p[0], p[1], p[2], p[3]);
uint32_t y = ntohl(x);
assert(y == 1);

如果您使用特定于操作系统的功能,那么编写端无关代码的意义何在? - Lundin
1
@Lundin:它们是POSIX函数。它也是Winsock的一部分。 - jxh
6
原帖中没有任何内容表明他们是否拥有操作系统... 无论如何,编写字节序检查并不特别困难,您不需要涉及某些API函数。int a = 0xAABBCCDD; if(*(uint8_t*)&a == 0xAA) puts("big") else puts("little"); - Lundin
@Lundin:如果我要为多个没有操作系统的平台编写跨平台代码,那么第一项任务就是将操作系统移植到每个平台。 - jxh
1
不,如果其中一个平台是嵌入式系统,你就不会这样做。通常的做法是将针对这些系统的代码放在计算机上,以创建和运行测试。 - Lundin
显示剩余6条评论

2
如果您想要独立于字节序的代码,那么您也需要平台无关的代码,否则您的要求就没有意义了。不依赖于字节序的代码不能依赖于int的大小,也不能依赖于char的有符号性。
为了获得真正可移植的代码,我想您需要编写类似于以下内容的代码:
#include <stdio.h>
#include <stdint.h>

#define INT_BITS (sizeof(int) * 8)

#define BYTE0_MASK (0xFFu << (INT_BITS -  8))
#define BYTE1_MASK (0xFFu << (INT_BITS - 16))

int main()
{
  int i = 0xAABBCCDD;
  unsigned char arr [2] =
  {
    (i & BYTE0_MASK) >> (INT_BITS -  8),
    (i & BYTE1_MASK) >> (INT_BITS - 16)
  };

  printf("%x %x", arr[0], arr[1]);    
}

1

如果您的程序不与其他程序进行通信(包括为另一个平台编写的同一程序),则字节序通常不是问题,除非您像问题中定义的联合那样做一些非常特殊的事情。当您的程序与其他程序进行通信时,例如将二进制数据保存到文件中,通过套接字发送数据,最好在格式/协议中明确定义字节序。或者您也可以以文本形式传输数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接