在这个答复中, zwol提出了这样的主张:
将两个字节的数据从外部源转换为16位有符号整数的正确方法是使用以下帮助函数:
#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;
}
上述哪个函数是合适的取决于数组是否包含小端或大端表示。Endianness不是这里的问题,我想知道为什么zwol从转换为int32_t
的uint32_t
值中减去0x10000u
。
为什么这是正确的方法?
转换为返回类型时如何避免实现定义的行为?
既然可以假设2的补码表示,那么这个更简单的强制转换将如何失败:return(uint16_t)val
这种天真的解决方案有什么问题:
int16_t le16_to_cpu_signed(const uint8_t data[static 2]) {
return (uint16_t)data[0] | ((uint16_t)data[1] << 8);
}
另一种方法-使用Union
:
union B2I16
{
int16_t i;
byte b[2];
};
节目中:
...
B2I16 conv;
conv.b[0] = first_byte;
conv.b[1] = second_byte;
int16_t result = conv.i;
第一个_字节
和第二个_字节
可以根据小端或大端模式进行交换。这种方法不是更好,而是一种替代方法。
int le16_to_cpu_signed(const uint8_t data[static 2]) {
unsigned value = data[0] | ((unsigned)data[1] << 8);
if (value & 0x8000)
return -(int)(~value) - 1;
else
return value;
}
因为分支,它会比其他选项更贵。
这样做的目的是,它避免了任何关于平台上int
表示与无符号
表示之间关系的假设。转换为int
需要保留适合目标类型的任何数字的算术值。因为反转确保16位数字的顶部位为零,所以该值将适合。然后一元-
和1的减法应用2的补码否定的一般规则。根据平台的不同,INT16_MIN
如果不适合目标上的int
类型,仍可能溢出,在这种情况下,应使用long
。
问题中与原始版本的差异出现在返回时间。虽然原始只是总是减去0x10000
和2的补码让签名溢出将其包装到int16_t
范围,但此版本具有显式的if
,避免了签名包装(未定义)。
现在在实践中,今天使用的几乎所有平台都使用2的补码表示。事实上,如果平台具有符合标准的stdint。定义
必须使用2的补码。这种方法有时适用于一些根本没有整数数据类型的脚本语言——您可以修改上面显示的浮点数操作,它将给出正确的结果。int32_t
的h
如果int
是16位,那么如果return
语句中表达式的值超出int16_t
的范围,则您的版本依赖于实现定义的行为。
然而,第一个版本也有类似的问题;例如,如果int32_t
是int
的typedef,并且输入字节都是0xFF
,那么返回语句中的减法结果是UINT_MAX
,这在转换为int16_t
时会导致实现定义的行为。
恕我直言,你链接到的答案有几个主要问题。
GCC和Clang似乎对有符号整数和无符号整数之间的加法有不同的解释,这取决于它们的大小。为什么会这样?所有编译器和平台上的转换是否一致? 举个例子: 结果: 在这两种情况下,我们得到了-1,但其中一个被解释为无符号整数和下溢。我本以为两者都会以同样的方式转化。 那么,为什么编译器会以如此不同的方式转换它们,这保证了一致性吗?我用G11.1.0和Clang12.0测试了这个。以及Arch Linu
问题内容: 在Java中,是否有一种简单而优雅的方法将无符号字节值转换为有符号字节值?例如,如果我所拥有的只是int值240(二进制(24位+ 11110000)= 32bits),如何获得该int的带符号值? 问题答案: 除了,Java没有其他无符号值。考虑以下代码段: 结果将为-1,因为最低的8位已复制到byte变量中。
问题内容: 给出以下代码: (第4版记入:casablanca) 您认为将char转换为int 的“ 最佳方法 ”是什么?(“ 最佳方式 ”〜= 惯用方式 ) 我们不是在转换char的实际数值,而是在转换表示形式的值。 例如。: 问题答案: 怎么样
问题内容: 在Python 3中将字节转换为十六进制字符串的正确方法是什么? 我看到了一种方法,编解码器的主张,并尝试了其他最小惊讶的可能功能,但无济于事。我只想要我的字节为十六进制! 问题答案: 从Python 3.5开始,这终于不再笨拙了: 并反向: 也适用于可变类型。 参考:https : //docs.python.org/3/library/stdtypes.html#bytes.hex
问题内容: 在Python中,有什么干净而优雅的方法可以将字符串“ 1,374”或“ 21,000,000”转换为int值(如1374或21000000)? 问题答案: 这实际上取决于您从哪里获得电话号码。 如果您尝试转换的数字来自用户输入,请使用。这样,将以与用户设置以及期望值一致的方式来解析数字。 另一方面,如果您从文件中读取文件,则该文件始终使用相同的格式,使用方式或取决于您的情况。这不仅易
我的目标是了解两者的互补性。 有符号整数中的等于。但是,如果您使用十六进制的或十进制的按位与它,它将等于。 在我看来,这不应该发生,因为顶部字节与结果字节相同 我的预期结果是该值不应该改变,它等于< code>-121。 我的实际结果是值发生变化。 我的猜测是,是一个。因此,顶部字节的有符号位和下部字节的无符号位将导致无符号位。但是......那不可能是对的。