8

我正在使用嵌入式平台(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。

4

5 回答 5

8

以下对我来说很好,正如评论所说,这是实现定义的:

int x = (signed char)(foo);

在 C++ 中,你也可以说:

int x = static_cast<signed char>(foo);

请注意,升级总是在重新解释位模式之前尝试保留该值。因此,您首先必须转换为与您的无符号类型相同大小的有符号类型以强制重新解释有符号。

(尝试将chars 打印为一对十六进制数字时,我通常会遇到相反的问题。)

于 2011-09-10T18:52:38.573 回答
6
uint8_t foo = 0xCE;          // 0b11001110
int8_t bar;
memcpy( &bar, &foo, 1 );

它甚至还有额外的好处,99% 的编译器将完全优化对 memcpy 的调用......

于 2011-09-10T19:10:26.910 回答
3

沿着这条线丑陋的东西?

int8_t bar = (foo > 127) ? ((int)foo - 256) : foo;

不依赖于行为未定义的转换。

于 2011-09-10T18:53:16.750 回答
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

干杯&hth.,

于 2011-09-10T18:54:55.533 回答
0

您可以使用指针访问值的表示。通过重新解释指针类型而不是值类型,您应该能够复制表示。

uint8_t foo = 0xCE;          
int8_t bar = *reinterpret_cast<int8_t*>(&foo);
于 2011-09-11T17:39:06.167 回答