C如何处理符号扩展?

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

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

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

 a = (int8_t)buffer[2*i] 

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

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 ,因此它们在赋值中保留,然后通过符号扩展完成对更宽类型int的保值提升。

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