将2个字节转换为带符号的16位整数的正确方法是什么? [英] What is the correct way to convert 2 bytes to a signed 16-bit integer?

查看:680
本文介绍了将2个字节转换为带符号的16位整数的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此答案中, zwol 提出了这样的要求:

In this answer, zwol made this claim:

将来自外部源的两个字节的数据转换为16位带符号整数的正确方法是使用以下辅助函数:

The correct way to convert two bytes of data from an external source into a 16-bit signed integer is with helper functions like this:

#include <stdint.h>

int16_t be16_to_cpu_signed(const uint8_t data[static 2]) {
    uint32_t val = (((uint32_t)data[0]) << 8) | 
                   (((uint32_t)data[1]) << 0);
    return ((int32_t) val) - 0x10000u;
}

int16_t le16_to_cpu_signed(const uint8_t data[static 2]) {
    uint32_t val = (((uint32_t)data[0]) << 0) | 
                   (((uint32_t)data[1]) << 8);
    return ((int32_t) val) - 0x10000u;
}

以上哪个函数合适取决于该数组包含的是小字节序还是大字节序表示.字节序不是这里要讨论的问题,我想知道为什么 zwol 从转换为int32_tuint32_t值中减去0x10000u.

Which of the above functions is appropriate depends on whether the array contains a little endian or a big endian representation. Endianness is not the issue at question here, I am wondering why zwol subtracts 0x10000u from the uint32_t value converted to int32_t.

为什么这是正确的方法?

在转换为返回类型时如何避免实现定义的行为?

How does it avoid the implementation defined behavior when converting to the return type?

由于可以假定2的补码表示形式,因此这种更简单的转换将失败:return (uint16_t)val;

Since you can assume 2's complement representation, how would this simpler cast fail: return (uint16_t)val;

这个天真的解决方案出了什么问题?

What is wrong with this naive solution:

int16_t le16_to_cpu_signed(const uint8_t data[static 2]) {
    return (uint16_t)data[0] | ((uint16_t)data[1] << 8);
}

推荐答案

如果int是16位,则如果return语句中表达式的值超出范围,则您的版本将依赖于实现定义的行为对于int16_t.

If int is 16-bit then your version relies on implementation-defined behaviour if the value of the expression in the return statement is out of range for int16_t.

但是第一个版本也有类似的问题;例如,如果int32_tint的typedef,并且输入字节均为0xFF,则return语句中的减法结果为UINT_MAX,当转换为int16_t时,将导致实现定义的行为

However the first version also has a similar problem; for example if int32_t is a typedef for int, and the input bytes are both 0xFF, then the result of the subtraction in the return statement is UINT_MAX which causes implementation-defined behaviour when converted to int16_t.

恕我直言,您链接到的答案有几个主要问题.

IMHO the answer you link to has several major issues .

这篇关于将2个字节转换为带符号的16位整数的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆