这里有很多问题,让我们看一下您的代码:
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,即扩展ASCII│ ( Box drawing character )
如果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
您有一个负值(最高位是有符号位)。
this:p[0]
实际上是一个“加法和引用”运算符。这意味着我们将获取 的地址p
,添加0
到它,然后遵从并查看结果:
p ---------+
V
------------------------------------------
| ptr(0xB3) | ? | ? | ... |
-------------------------------------------
0xbfd56c2b 0xbfd56c2C 0xbfd56c2d ...
当你这样做时,p[1]
会超过 ptr 一个char
或一个字节并给你那个结果。什么东西在那里?不知道。这超出了您的范围:
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