【问题标题】:Union and endianness联合和字节序
【发布时间】:2013-09-22 17:19:24
【问题描述】:
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 的字节顺序吗?

【问题讨论】:

  • 你想达到什么目的?
  • 根据字节序,第二行的输出会改变,对吧?我想编写与平台无关的代码。

标签: c cpu endianness


【解决方案1】:

您可以使用htonl() and/or ntohl()htonl() 代表“主机到网络长”,而ntohl() 代表“网络到主机长”。 “主机”和“网络”是指字节顺序。网络字节顺序是“大端”。如果主机平台也是“大端”,则操作将是无操作的。使用这些例程,以下程序将始终报告相同的输出:

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:它们是 POSIX 函数。它也是 Winsock 的一部分。
  • 原帖中没有任何内容表明他们甚至有操作系统......无论如何,自己编写字节序检查并不是特别难,你不需要涉及一些API函数. int a = 0xAABBCCDD; if(*(uint8_t*)&a == 0xAA) puts("big") else puts("little");.
  • @Lundin:如果我要为多个没有操作系统的平台编写独立于平台的代码,那么首要任务就是将操作系统移植到每个平台。
  • 不,如果其中一个平台是嵌入式系统,你不会。通常的做法是将用于此类系统的代码放入您的 PC 中,然后在其上创建和运行测试。
【解决方案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]);    
}

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-08
      • 2016-12-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多