这里有不少问题,我们来看看你的代码:
int main ()
{
char addr = 0xB3; <-- you're asigning 0xB3 in hex, which is (179 in dec) to addr
char *p = &addr; <-- you're assigning a pointer to point to addr
如果 addr 未签名,现在将设置为 179,即 │ ( Box drawing character ) 的 extended ASCII
char 的值可以是 -127 到 +127,如果它是有符号的,或者是 0 到 255,如果它是无符号的。在这里(根据您的输出)它已签名,因此您的分配溢出了 char。
printf ("%c, %c\n", p[0], p[1]); <-- print the char value of what p is pointing to
also, do some UB
printf ("%X, %X\n", p[0], p[1]); <-- print the hex value of what p is pointing to
also, do some UB
因此,您的代码的第二部分在这里打印溢出的 addr var 的 char 值,它恰好为您打印 '?'。 addr 的十六进制值是 FFFFFFB3 表示您有一个负值(最高位是有符号位)。
这:p[0] 实际上是一个“添加和引用”运算符。意思就是我们要取p的地址,加上0,然后顺从看看结果:
p ---------+
V
------------------------------------------
| ptr(0xB3) | ? | ? | ... |
-------------------------------------------
0xbfd56c2b 0xbfd56c2C 0xbfd56c2d ...
当您执行 p[1] 时,这将经过一个 char 或一个字节超过 ptr 并为您提供该结果。什么东西在那里?不知道。这超出了您的范围:
p+1 -------------------+
V
------------------------------------------
| ptr(0xB3) | ? | ? | ... |
-------------------------------------------
0xbfd56c2b 0xbfd56c2C 0xbfd56c2d ...
Y 的 ASCII 值(十六进制)是 0x59,所以内存中的指针后面是 Y。但它可能是任何东西,将要做什么是未定义的。正确的做法是:
int main ()
{
unsigned char addr = 0xB3;
char low = addr & 0x0F;
char high = (addr >> 4) & 0x0F;
printf("%#x becomes %#x and %#x\n", addr, high, low);
return 0;
}
这通过以下方式工作:
0xB3 => 1011 0011 0xB3 >> 4 = 0000 1011
& 0000 1111 & 0000 1111
------------ -------------
0000 0011 => 3 low 0000 1011 => B high