我正在研究嵌入式平台(ARM),在处理位模式时必须小心。让我们假装这条线超出了我的影响力:
uint8_t foo = 0xCE; // 0b11001110
解释为无符号,这将是206.但实际上它是签名的,因此类似于 -50 。如何继续将此值用作签名?
int8_t bar = foo; // doesn't work
两者都没有(导致所有输入值为0x10或0x00)
int8_t bar = static_cast<int8_t>(foo);
int8_t bar = reinterpret_cast<int8_t&>(foo);
我只是希望这些位保持不变,即。 (bar == 0xCE)
反之亦然我感兴趣的是如何将代表负数的位模式转换为无符号变量而不会弄乱位模式。我正在使用GCC。
答案 0 :(得分:8)
以下对我来说很好,应该虽然评论说这是实现定义的:
int x = (signed char)(foo);
在C ++中,您也可以说:
int x = static_cast<signed char>(foo);
请注意,在重新解释位模式之前,促销始终会尝试保留值。因此,您首先必须转换为与无符号类型相同大小的签名类型,以强制进行签名重新解释。
(当我尝试将char
打印成十六进制数字对时,我通常面临相反的问题。)
答案 1 :(得分:5)
uint8_t foo = 0xCE; // 0b11001110
int8_t bar;
memcpy( &bar, &foo, 1 );
它甚至还有额外的好处,即99%的编译器会完全优化对memcpy的调用......
答案 2 :(得分:3)
有些丑陋吗?
int8_t bar = (foo > 127) ? ((int)foo - 256) : foo;
不依赖于行为未定义的转换。
答案 3 :(得分:0)
GCC很可能无符号值是两个补码,即使在您的嵌入式平台上也是如此。
然后,8位数字0xCE
代表0xCE-256
。
因为两个补码实际上只是模2 n ,其中 n 是表示中的位数。
编辑:嗯,为了代表我最好给出一个具体的例子:
int8_t toInt8( uint8_t x )
{
return (x >= 128? x - 256 : x);
}
编辑2 :我没有看到关于如何将一个模式转换为无符号变量的最终问题。这非常简单:只需分配即可。结果由C ++标准保证,即存储的值与指定的值一致(在时钟面上相等),模2 n 。
干杯&amp;第h。,
答案 4 :(得分:0)
您可以使用指针访问值的表示。通过重新解释指针类型而不是值类型,您应该能够复制表示。
uint8_t foo = 0xCE;
int8_t bar = *reinterpret_cast<int8_t*>(&foo);