【问题标题】:BIG_ENDIAN code to be fixed for LITTLE_ENDIAN machine as well也为 LITTLE_ENDIAN 机器修复 BIG_ENDIAN 代码
【发布时间】:2015-07-30 20:47:33
【问题描述】:

我有这段遗留代码,我需要在 BIG 和 LITTLE Endian 机器上运行。问题出在 hton() 上。

msg->Mac 是字符 Mac[16+1] 现有代码:(仅适用于 BIG)

if (sscanf(msg->Mac, "%4hx.%4hx.%4hx", (unsigned short *)&new_mac[0],
              (unsigned short *)&new_mac[2],
              (unsigned short *)&new_mac[4]) != 3) {
  return (ERROR_ADDRESS_TRANSLATION);
 }

*(unsigned short *)&new_mac[0] = hton(*(unsigned short *)&new_mac[0]);
*(unsigned short *)&new_mac[2] = hton(*(unsigned short *)&new_mac[2]);
*(unsigned short *)&new_mac[4] = hton(*(unsigned short *)&new_mac[4]);

sprintf((char *)newMac, "%04x.%04x.%04x", *(unsigned short *)&new_mac[0],
        *(unsigned short *)&new_mac[2], *(unsigned short *)&new_mac[4]);

 /* Get the MAC address */
if (sscanf((char *)newMac, "%4hx.%4hx.%4hx", (unsigned short *)&mac_addr[0],
              (unsigned short *)&mac_addr[2],
              (unsigned short *)&mac_addr[4]) != 3) {
      return (ERROR_ADDRESS_TRANSLATION);
 }


 /* Convert to network order */
 *(unsigned short *)&mac_addr[0] = hton(*(unsigned short *)&mac_addr[0]);
 *(unsigned short *)&mac_addr[2] = hton(*(unsigned short *)&mac_addr[2]);
 *(unsigned short *)&mac_addr[4] = hton(*(unsigned short *)&mac_addr[4]);

为了在 LITTLE Endian 机器上解决这个问题,我使用了一个 SWAP 宏,它将在短时间内交换字节。这是正确的方法吗?

我在上面添加的代码:(使其也适用于 LITTLE)

#if __BYTE_ORDER != __BIG_ENDIAN

*(unsigned short *)&mac_addr[0] = SWAP(*(unsigned short *)&mac_addr[0]);
*(unsigned short *)&mac_addr[2] = SWAP(*(unsigned short *)&mac_addr[2]);
*(unsigned short *)&mac_addr[4] = SWAP(*(unsigned short *)&mac_addr[4]);

#endif

【问题讨论】:

  • msg->Mac 是字符 Mac[16+1]
  • 你为什么交换?为什么直接打印,为什么不打印ntoh(new_mac[..])?
  • @WernerHenze 你的意思是我应该再次为 LITTLE 做 ntoh 吗?
  • 是的。 sscanf 读取并存储主机字节顺序,然后您将 hton 用于网络字节顺序,然后将其打印出来。因此,如果您的主机字节顺序与网络字节顺序相同,则打印出您输入的内容。如果主机字节顺序不是网络字节顺序,则打印出交换的字节。解决方案不是交换,而是在打印前交换到 ntohs。请告诉我这是否回答了您的问题(我并不完全清楚),然后我可以将其写成您可以接受的答案。

标签: c++ endianness


【解决方案1】:

你在小端机器上测试过吗?由于 hton 已经考虑了拱字节:

/* Copyright (C) 1993-2015 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.  */

#include <stdint.h>
#include <netinet/in.h>

#undef  htonl
#undef  ntohl

uint32_t
htonl (uint32_t x)
{
#if BYTE_ORDER == BIG_ENDIAN
  return x;
#elif BYTE_ORDER == LITTLE_ENDIAN
  return __bswap_32 (x);
#else
# error "What kind of system is this?"
#endif
}
weak_alias (htonl, ntohl)

【讨论】:

  • 是的,它不适用于 LITTLE Endian。 mac "0000.a123.ac12" 打印为 0000.ffffff23ffffffa1.12ac
【解决方案2】:

特别是对于 MAC 地址:它们应该被视为一个 6 字节的数组,所以应该没有字节序问题。尝试映射其他类型(为了提高效率?)只是自找麻烦。

所以 scanf 应该是:

sscanf(msg->Mac, "%2hhx%2hhx.%2hhx%2hhx.%2hhx%2hhx", 
              &new_mac[0], &new_mac[1],
              &new_mac[2], &new_mac[3],
              &new_mac[4], &new_mac[5])

【讨论】:

  • 我知道那将是最好的方法。但是我正在处理遗留代码,现在无法在以后的代码中进行更改。 new_mac 可以在多个地方访问。
  • 所以在这里执行此操作会在代码的其他地方出现问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-12
  • 1970-01-01
  • 1970-01-01
  • 2019-11-25
  • 2018-11-23
  • 2021-12-14
  • 1970-01-01
相关资源
最近更新 更多