2

我发现了一些我无法解释的奇怪现象。如果这里有人可以看到这是什么或为什么会发生,我想知道。我正在做的是采用一个包含 12 位高对齐的无符号短,如下所示:

1111 1111 1111 0000

然后我想改变这些位,以便短字节中的每个字节保持 7 位,并将 MSB 作为填充。上面显示的结果应如下所示:

0111 1111 0111 1100

我所做的是这样的:

unsigned short buf = 0xfff;
//align high
buf <<= 4;

buf >>= 1;
*((char*)&buf) >>= 1;

这给了我一些看起来像是正确的东西,但是最后一次移位的结果使位设置如下:

0111 1111 1111 1100

很奇怪。如果我使用 unsigned char 作为临时存储并转移它,那么它就可以工作,如下所示:

unsigned short buf = 0xfff;
buf <<= 4;

buf >>= 1;
tmp = *((char*)&buf);
*((char*)&buf) = tmp >> 1;

结果是:

0111 1111 0111 1100

有什么想法吗?

4

2 回答 2

4

是的,它看起来像是char在您的平台上签名的。如果你这样做了*((unsigned char*)&buf) >>= 1,它会起作用的。

于 2010-05-16T18:08:09.663 回答
1

让我们分解一下。我假设您的编译器将 short 视为 16 位内存。

unsigned short buf = 0xfff; 
//align high 
buf <<= 4; 

相当于:

unsigned short buf = 0xfff0;

... 和

buf >>= 1; 

应该导致 buf 的值为 0x7ff8 (即第 th 位向右移动一位)。现在为您的花哨的线:

*((char*)&buf) >>= 1; 

这里发生了很多事情......首先需要解决左侧问题。您所说的是获取 buf 并将其视为指向 8 位内存的指针(而不是自然的 16 位)。buf 最初引用的两个字节中的哪一个依赖于知道你的内存字节序是什么(如果它是 big-endian buf 指向 0x7f,如果它是 little-endian buf 指向 0xf8)。我假设你在一个 Intel 盒子上,这意味着它的小端,现在 buff 指向 0xf8。然后,您的语句说分配给该字节,该字节的值向右移动(并且符号扩展,因为 char 已签名)向右移动 1 或 0xfc。另一个字节将保持不变。如果您不想要符号扩展,请将 buf 改成 (unsigned char *)。

于 2010-05-16T18:10:55.773 回答