printf 在这里做了什么?

what did printf do here?

只是我在测试我对指针的理解,同时我这样做了,

好的,这就是我的想法。
所有指向任何类型的指针都保存地址,对吗?
说我声明
char *a, b = 'f'; a = &b ;
因此,当我尝试访问 b 的内容即 &b 时,通过指向类型 char.which 的指针是可以的。

但是,如果我将 int 数据类型的地址存储在 char 类型的指针中怎么办(尽管我收到警告:从不兼容的指针类型 [-Wincompatible-pointer-types] 赋值,我没有做错,对吧?。我还在存储一些内存的地址。)

int main(){
// int type of one byte
    int a, i ;
    char *b;

    for(i = -256 ;i < 257; ++i){
        a = i;
        b = &a;
        printf("for i = %d, value stored in first byte of a = %d\n",i ,*b);
    }
    return 0;    
}


现在我认为只允许读取分配给 a 的 4 个字节的第一个字节,因为我正在通过一个指向 char 类型的指针进行访问,我希望存储最多 255 个值,超出这个值就会溢出。
但它发生了一些不同的事情,我只能存储 127 到 -128 whao!!。你看到它是一个大小为 1 的 int 类型吗 byte.You 可以 运行 代码来查看。


现在假设 int 类型的大小为一个字节

当 a = 256 时,读取的值为 0,这是预期的,因为 0001 0000 0000 它只会读取第一个字节。
输出是可预测的,直到我们达到 a = 127,它存储为 0111 1111(从 int 类型的角度来看是正值)
当 a = 128 时,输出为 -128 ,存储为 1000 0000 (实际上是 -128)
同样可以解释其他输出
因此可以通过假设 int 类型的大小为一个字节来解释输出,为什么 printf 这样做而不是抛出错误。

那么 printf 到底做了什么?
谢谢各位大人;)

您的系统使用带符号的字符,这是完全正常的。

您似乎 assume/expect charunsigned,但这并不总是正确的。它要么是有符号的,要么是无符号的,但这取决于实现。

But, What if i store address of int data type in a pointer of char type(although i get warning: assignment from incompatible pointer type [-Wincompatible-pointer-types], i'm not doing wrong, right?.i'm still storing address of some memory.)

是的,你做错了什么,这就是你收到警告的原因。

指针类型很重要有两个原因:

  1. 指针运算是根据对象而不是字节来完成的。如果 p 是一个 char * 并且它的值是一个 char 对象的地址(比如 0x1000),那么 p + 1 计算为下一个 char 对象 (0x1001)。如果 p 是一个 int * 并且它的值是一个 4 字节 int 对象 (0x2000) 的地址,则 p + 1 计算为下一个 4 字节 int 对象 (0x2004).

  2. 与其他类型一样,不同的指针类型可能具有不同的大小和表示形式。 int * 可能与 char * 具有不同的表示形式。在 x86 和 x86_64 等大多数现代系统上,它们是相同的,但在一些较旧或古怪的体系结构中,情况并非如此。

So output can be explained by assuming that int type is of size one byte, why did printf do that instead of throwing error.

问题不在于 printf,问题在于您在尝试将 128 分配给 [时遇到 有符号整数溢出 =28=],因为在您的系统上 char 占据范围 [-128..127]。不幸的是,有符号整数溢出的行为是 undefined - 不要求您的实现以任何特定方式处理它。我所知道的大多数实现根本不会尝试处理它——你只会得到一个意想不到的值。假设有多个有符号整数表示,并且假设许多实现依赖于未定义的行为来执行某些优化,您可以获得几乎 any 结果。