%x格式说明符,在C中带有unsigned char

Rob*_*nes 8 c

我遇到了以下示例程序,但我并不完全理解它的输出:

#include <stdio.h>

int main( void ) {

    unsigned char i, m =0xFF, n=0x1;

    for ( i = 0; i != 8; i++,n+=n, m/=2 )
        printf("%5x %5x %5x %5x %5x %5x\n", n,m,n&m,n|m,n^m,~n);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

打印出来:

    1    ff     1    ff    fe fffffffe
    2    7f     2    7f    7d fffffffd
    4    3f     4    3f    3b fffffffb
    8    1f     8    1f    17 fffffff7
   10     f     0    1f    1f ffffffef
   20     7     0    27    27 ffffffdf
   40     3     0    43    43 ffffffbf
   80     1     0    81    81 ffffff7f
Run Code Online (Sandbox Code Playgroud)

问题是最后一栏.由于它是unsigned char,我希望它在每列中只打印2个位置. ~n生成一个unsigned char作为结果,但似乎它被转换为带符号的32位值并由符号扩展符号%5x.

怎么可能,这里发生了什么?

Die*_*Epp 10

在算术运算中使用整数类型时会提升它们(printf顺便说一下,这与它无关).

所以,例如,

unsigned char x = 0xff;
int y = ~x; // x is promoted to 0x000000ff, then changed to 0xffffff00
unsigned char z = ~x; // truncated back to 0x00
Run Code Online (Sandbox Code Playgroud)

整数提升会导致各种问题:

unsigned char x = 1;
if (x << 8)
    puts("x << 8 is true"); // does print
x <<= 8;
if (x)
    puts("x <<= 8 is true"); // does not print
Run Code Online (Sandbox Code Playgroud)

截断事物的两种方法是强制转换和掩码.用你喜欢的任何东西.

unsigned char x = 0xab;
printf("x = %02x\n", (unsigned char) x);
printf("x = %02x\n", x & 0xff);
Run Code Online (Sandbox Code Playgroud)

整数提升并不总是发生,并且它不是唯一的隐式演员.它也有点微妙,准确的规则很难记住.如果你正在使用64位数字,你真的需要担心它,因为1U << 32最终会成为0或者1完全不同.(它通常1在x86上).