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 char
是 unsigned
,但这并不总是正确的。它要么是有符号的,要么是无符号的,但这取决于实现。
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.)
是的,你做错了什么,这就是你收到警告的原因。
指针类型很重要有两个原因:
指针运算是根据对象而不是字节来完成的。如果 p
是一个 char *
并且它的值是一个 char
对象的地址(比如 0x1000
),那么 p + 1
计算为下一个 char
对象 (0x1001
)。如果 p
是一个 int *
并且它的值是一个 4 字节 int
对象 (0x2000
) 的地址,则 p + 1
计算为下一个 4 字节 int
对象 (0x2004
).
与其他类型一样,不同的指针类型可能具有不同的大小和表示形式。 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 结果。
只是我在测试我对指针的理解,同时我这样做了,
好的,这就是我的想法。
所有指向任何类型的指针都保存地址,对吗?
说我声明
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 char
是 unsigned
,但这并不总是正确的。它要么是有符号的,要么是无符号的,但这取决于实现。
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.)
是的,你做错了什么,这就是你收到警告的原因。
指针类型很重要有两个原因:
指针运算是根据对象而不是字节来完成的。如果
p
是一个char *
并且它的值是一个char
对象的地址(比如0x1000
),那么p + 1
计算为下一个char
对象 (0x1001
)。如果p
是一个int *
并且它的值是一个 4 字节int
对象 (0x2000
) 的地址,则p + 1
计算为下一个 4 字节int
对象 (0x2004
).与其他类型一样,不同的指针类型可能具有不同的大小和表示形式。
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 结果。