【问题标题】:Convert unsigned char to unsigned short (big endian)将 unsigned char 转换为 unsigned short(大端)
【发布时间】:2018-01-26 14:51:33
【问题描述】:

我有一个 LabVIEW 程序(不是我的),它将数据(uint16)保存在二进制文件中,如下所示:

  • 将数字除以 2^8 得到 2 uint8(例如 320 = 256 + 64)
  • 切换之前的数据保存(所以这里以64开始,以256结束)

这就是为什么我读 4 个八位字节得到 2 个无符号短字节

ifstream is("filename", ifstream::binary);
if (is) {
    is.seekg(0, is.end);

    unsigned char data_char[4];
    unsigned short data;

    is.seekg(376, is.beg);
    is.read(reinterpret_cast<char*>(width), sizeof(width));

    // What I tried (switch and convert)
    data = data_char[1]<<24 + data_char[0]<<16 + data_char[3]<<8 + data_char[2];
}

例如,值 320 (uint8) 保存在文件中,当我读取 data_char 时,我有一个 unsigned char 与数字的 4 个组合:

  • [0] = 0 '\0'
  • [1] = 64 '@'
  • [2] = 1 '\x1'
  • [3] = 0 '\0'

我有 256 个:

  • [0] = 1 '\x1'
  • [1] = 0 '\0'
  • [2] = 0 '\0'
  • [3] = 0 '\0' [0] 和 [1] 是第一个 uint8,[2] 和 [3] 是第二个。

但是,作为 C++ 的新手,我尝试了一些移位来将 char 转换为 short,但我的方法不正确。

我知道这对你来说很容易,但请你帮助我吗?

有关信息,我只需要在 Python 中执行以下操作:sum(struct.unpack("&gt;HH", f.read(4))

【问题讨论】:

  • 我建议使用htons()/ntohs() 来做到这一点。
  • 你不是自己写答案data_char[2]*256 + data_char[1]吗?您不必通过位移来完成。
  • 是的,但是这个解决方案承认我的数据总是在我的 char 的 2d 和 3th 索引上。所以它不是通用的。我说这是因为在我必须以 little endian 和 uint16 读取其他数据之后,所以我必须先了解基础;)
  • 嗯,答案总是second_byte*256 + first_byte。这是普遍的。
  • 好吧,例如,256 将是 1、0、0、0。如果我按照你的建议做,我会找到 0。

标签: c++ type-conversion


【解决方案1】:

要将大字节序转换为原生字节序,只需将字节按字节的位宽乘以字节位置的差异和整数的大小,然后将所有内容与按位或相结合。

更具体地说:第一个字节移位最显着,最后一个字节根本不移位。

template<class T>
T my_ntoh(unsigned char* buf) {
    const auto s = sizeof(T);
    T value = 0;
    for (unsigned i = 0; i < s; i++)
        value |= buf[i] << CHAR_BIT * (s - 1 - i);
    return value;
}

此模板适用于任何大小的整数,并且将读取与整数类型大小一样多的字节。

如果你可以依赖POSIX,它提供ntohs,所以你不必自己写这个转换。


由于您想读取两个大端无符号短裤并将它们相加(我使用uint16_t,因为它保证为 2 个八位字节):

auto part1 = my_ntoh<uint16_t>(data_char);
auto part2 = my_ntoh<uint16_t>(data_char + sizeof part1);
data = part1 + part2;

【讨论】:

  • 这个解决方案很酷。唯一的问题(我编辑了我的帖子)是我看到在保存过程中有字节切换。但不要删除您的答案,因为它可能适用于我的代码的另一个地方^^
  • 看起来 OP 有 little-endian 编码,每个字节都是 16 位,哈哈。实际上没有,unsigned short 被分成两个字节,每个字节存储为无符号短。怪人
  • @MathieuGauquelin 如果你愿意,你可以这样做。这正是我的程序所做的,除了我的函数也可以用来读取其他大小的整数。除了我使用 + 而不是 |合并这些部分,因为我不清楚是否 |有道理。只要这两个部分不共享任何设置位,结果就相同。然而,对我来说,你的台词就像一个魔法咒语。从我的函数调用中,我清楚地看到我读取并转换了两个连续的短裤并将它们加在一起。
  • @MathieuGauquelin 没有。移位方向始终向左。对于小端,您最多移动最后一个字节,而根本不移动第一个字节。所以在我的函数中用i替换s - 1 - i
  • @MathieuGauquelin 因为它支持返回不同类型的整数:short、int、long 和 long long 的无符号版本以及实现定义的整数。非模板函数只能有一种返回类型。
【解决方案2】:

你真的应该使用特殊的标准函数来做到这一点。看看htons()ntohs()(简称主机到网络和网络到主机)。在线查找有关它们的文档(特定于您的系统)并不麻烦,这里有一个这样的页面:http://beej.us/guide/bgnet/html/multi/htonsman.html

【讨论】:

  • 但是,如果一开始它以标准方式保存,那就太好了,我的情况不是这样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-22
  • 2015-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-11
  • 1970-01-01
相关资源
最近更新 更多