C如何处理符号扩展?

时间:2012-10-21 15:57:24

标签: c unsigned signed

我有一个指向字节缓冲区的指针,我将每个偶数索引字节复制到一个int(因为数据存储到缓冲区的协议我知道奇数周期用于读取)。 现在当我这样做时

signed int a;
...
//inside a loop
a = buffer[2*i]; //buffer is unsigned

它给了我一个未签名的号码。但是当我这样做时

a = (int8_t)buffer[2*i]

该号码以签名形式呈现。这迫使我重新思考c中的符号扩展如何工作,特别是在上面的场景中。 我的理解是,因为我声明一个已签名的编译器将自动执行符号扩展。任何人都可以花点时间解释为什么不是这种情况。我只是花了一个小时在这个陷阱中,并且不希望将来再陷入同一陷阱。

2 个答案:

答案 0 :(得分:2)

buffer是一个无符号的8位整数数组(或作为一个整数)。因此buffer[2*i]的值在0到255(包括)范围内,并且该范围内的所有值都可以表示为int s,因此分配

a = buffer[2*i];

保留该值,通过用零填充来完成对更宽类型int的提升。

如果您在分配前转换为int8_t

a = (int8_t)buffer[2*i]

缓冲区中大于127的值以实现定义的方式转换为类型int8_t,最有可能的方法是将位模式重新解释为带符号的8位整数,从而产生负值,从-128到-1。这些值可以表示为int s,因此它们会保留在分配中,然后通过符号扩展来保留对更宽类型int的保值促销。

答案 1 :(得分:1)

int_8只有8位,如果最高位为1则保持负值:1xxxxxxx,如果将这样的值赋给signed int(32或64位),当然你会得到一个负值。在赋值之后,较长的int看起来像11111111 11111111 11111111 1xxxxxxx,只需要一个简单的xor即可完成技巧00000000 ^ 1001 => 11111001