将 uint16_t 解释为 int16_t

发布于 2024-12-05 11:32:01 字数 223 浏览 4 评论 0原文

是否有一种可移植且安全的方法将 boost::uint16_t 生成的位模式解释为 boost::int16_t ?我有一个 uint16_t,我知道它代表一个编码为小端的有符号 16 位整数。我需要对这个值进行一些有符号算术,那么有没有办法让编译器相信它已经是有符号值了?

如果我没有记错的话,static_cast 会转换该值,也许会更改其位模式。

Is there a portable and safe way to interpret the bit-pattern made by a boost::uint16_t as a boost::int16_t? I have a uint16_t, which I know represents a signed 16-bit integer encoded as little-endian. I need to do some signed arithmetic on this value, so is there anyway to convince the compiler that it already is a signed value?

If I a not mistaken, a static_cast<int16_t> would convert the value, perhaps changing its bit-pattern.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

像极了他 2024-12-12 11:32:01

如果您正在寻找与强制转换不同的东西,那么请将其内存表示复制到 boost::int16_t 的内存表示,因为它一开始就表示它的含义。

编辑:如果您必须使其在大端机器上工作,只需向后复制字节即可。使用 std::copystd::reverse

If you are looking for something different than a cast, then copy its memory representation to that of a boost::int16_t since its what it represents to begin with.

Edit: If you have to make it work on a big endian machine, simply copy the bytes backwards. Use std::copy and std::reverse.

∞梦里开花 2024-12-12 11:32:01

只需使用静态转换即可。如果您碰巧位于以不同方式定义位模式的平台上,则更改位模式恰好正是您想要的。

reinterpret_cast 或任何等效的指针转换未定义(未定义实现)。这意味着编译器可以随意做一些令人讨厌的事情,例如将未定义的形式缓存在寄存器中并错过更新。此外,如果您使用的平台上的位模式不同,那么绕过转换会给您留下垃圾(就像假装浮点数是 int 并向其添加 1 一样。)

更多信息位于 C 中的有符号到无符号转换 - 总是安全吗? 但摘要C、环岛内方式,将静态强制转换(实际上是普通的 C 强制转换)定义为通过在 x86 上处理相同的位(使用二进制补码)所得到的结果

。不会通过更改来破坏每个人的代码)。历史已经证明你错了。

Just use the static cast. Changing the bit pattern happens to be exactly what you want, if you happen to be on a platform that defines them differently.

reinterpret_cast, or any equivalent pointer cast, is undefined (not implementation defined). That means the compiler is free to do nasty things like cache the undefined form in a register and miss the update. Besides, if you were on a platform where the bit patterns were different then bypassing the conversion would leave you with garbage (just like pretending a float is an int and adding 1 to it.)

More info is at Signed to unsigned conversion in C - is it always safe? but the summary C, in a roundabout way, defines the static cast (ordinary C cast actually) as exactly what you get by treating the bits the same on x86 (which uses two's complement.)

Don't play chicken with the compiler (this always worked on this compiler so surely they won't break everybody's code by changing it). History has proven you wrong.

菊凝晚露 2024-12-12 11:32:01

屏蔽除符号位之外的所有内容,将其存储在有符号 int 中,然后使用符号位设置符号。

Mask off all but the sign bit, store that in a signed int, then set the sign using the sign bit.

仙气飘飘 2024-12-12 11:32:01

我猜 *(boost::int16_t*)(&signedvalue) 会起作用,除非你的系统架构默认不是小端。 endian ness 将改变行为,因为在上述操作之后,cpu 会将带符号的值视为特定于体系结构 boost::int16_t 值(这意味着如果您的体系结构是大 endian,则会出错)。

I guess *(boost::int16_t*)(&signedvalue) would work, unless your system architecture is not little-endian by default. endian ness will change behavior since after above operation cpu will treat signed value as a architecture specific boost::int16_t value (meaning if your architecture is big endian it'll go wrong).

忆离笙 2024-12-12 11:32:01

编辑
为了避免对 *(int16_t)(&input_value) 产生争议,我将代码块中的最后一条语句更改为 memcpy 并添加了 *(int16_t)(& ;input_value) 作为附录。 (反之亦然)。

在大端机器上,您需要进行字节交换,然后解释为有符号整数:

if (big_endian()) {
  input_value = (uint16_t)((input_value & 0xff00u) >> 8) |
                (uint16_t)((input_value & 0x00ffu) << 8);
}
int16_t signed_value;
std::memcpy (&signed_value, &input_value, sizeof(int16_t));

在大多数计算机上,您可以将对 memcpy 的调用更改为 signed_value = *(int16_t)(& ;输入值);。严格来说,这是未定义的行为。这也是一个使用极为广泛的习语。几乎所有编译器都用这个语句做了“正确的事情”。但是,正如语言扩展的情况一样,YMMV。

Edit
To avoid controversy over *(int16_t)(&input_value), I changed the last statement in the code block to memcpy and added *(int16_t)(&input_value) as an addendum. (It as the other way around).

On a big endian machine you will need to do a byte swap and then interpret as a signed integer:

if (big_endian()) {
  input_value = (uint16_t)((input_value & 0xff00u) >> 8) |
                (uint16_t)((input_value & 0x00ffu) << 8);
}
int16_t signed_value;
std::memcpy (&signed_value, &input_value, sizeof(int16_t));

On most computers you can change the call to memcpy to signed_value = *(int16_t)(&input_value);. This is, strictly speaking, undefined behavior. It is also an extremely widely used idiom. Almost all compilers do the "right thing" with this statement. But, as is always the case with extensions to the language, YMMV.

勿忘初心 2024-12-12 11:32:01

作为一种不同的策略,最大化(但不能确保)可移植性的最佳方法是将这些有符号 16 位整数按网络顺序存储为有符号 16 位整数,而不是按小端顺序存储为无符号 16 位整数。这给目标机器带来了负担,需要能够将这些 16 位网络顺序有符号整数转换为目标的本机形式的 16 位有符号整数。并非每台机器都支持此功能,但大多数可以连接到网络的机器都支持。毕竟,该文件必须通过某种机制到达目标计算机,因此它很有可能理解网络顺序。

另一方面,如果您通过某些专有串行接口将该二进制文件传输到某些嵌入式机器,那么可移植性问题的答案与您告诉医生“我这样做时会很痛”时得到的答案相同。

As a different tack, the best way to maximize (but not ensure) portability is to store those signed 16 bit integers as signed 16 bit integers in network order rather than as unsigned 16 bit integers in little endian order. This puts the burden on the target machine to be able to translate those 16 bit network order signed integers to 16 bit signed integers in the native form to the target. Not every machine supports this capability, but most machines that can connect to a network do. After all, that file has to get to the target machine by some mechanism, so the odds are pretty good that it will understand network order.

On the other hand, if you are zapping that binary file to some embedded machine via some proprietary serial interface, the answer to the portability question is the same answer you'll get when you tell your doctor "it hurts when I do this."

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文