在 C 中使用指针访问 int 变量中的字符

Accessing a character from int variable using pointer in C

为什么下面代码的输出是-127。为什么不应该是 -1?

#include<stdio.h>
int main(){
    int a = 129;
    char *ptr;
    ptr = (char *)&a;
    printf("%d ",*ptr);
    return 0;
}

如果您将以十六进制输出变量 a,您将看到它表示为 0x81

这是一个演示程序。

#include <stdio.h>

int main(void) 
{
    int a = 129;
    
    printf( "%#x\n", a );
    
    return 0;
}

它的输出是

0x81
如果 char 类型的行为与 signed char 类型相同,

0x80 是 char 类型对象的最小值。此值等于十进制值 -128.

这是另一个演示程序。

#include <stdio.h>

int main(void) 
{
    char c = -128;
    
    printf( "%#hhx\n", c );
    
    return 0;
}

它的输出是

0x80

如果加上 1 你会得到值 -127.

字符值 -1 的二进制补码表示形式类似于 0xff 的十六进制形式。如果添加 1 你会得到 0.

将signed char转int后,剩下的24位填什么? 答案并不总是“0”,而是 'sign bit' -- 最高位 -- .

您可能会对以下演示代码感兴趣:

#include<stdio.h>
int main(){
    int a = 129;
    char *ptr;
    ptr = (char *)&a;
    
    // output "0x81", yes  129 == 0x81
    printf("0x%hhx\n",*ptr);


    // output 0xffffff81
    int b = *ptr;   // convert a 'signed char' to 'int'
                    // since the 'sign bit' of the char is 'minus', so left padding that much '1'
    printf("0x%x\n",b);
    
    unsigned char *ptru = (unsigned char *)&a;
    b = *ptru;
    printf("0x%x\n",b);  // still, output "0x81" 

    return 0;
}

可以这样理解:

我们都知道(signed)char的取值范围是[-128 to 127],现在我们把这个取值范围分解成二进制,那么,需要的位数是8(1 字节)

0 : 0000 0000
1 : 0000 0001
2 : 0000 0010
3 : 0000 0011
...
126 : 0111 1110
127 : 0111 1111 <-- max +ve number 因为之后我们将溢出符号位
-128 : 1000 0000 <-- 奇怪的数字 因为数字和它的 2 的补码相同。
-127 : 1000 0001
-126 : 1000 0010
...
-3 : 1111 1101
-2 : 1111 1110
-1 : 1111 1111


所以,现在回到问题,我们有 int a = 129;,显然 129 当存储在 char 数据类型中时,它将溢出作为最大正允许值是 127但为什么我们得到的是 -127 而不是其他东西?

129 的简单二进制等价物是 1000 0001 而对于 char data-type 来说,

127 : 0111 1111
-128 : 1000 0000
-127 : 1000 0001<-- 这里!
-126 : 1000 0010
...
因此,当 129 存储在其中时,我们得到 -127