只是我在测试我对指针的理解,同时我这样做了,
好的,这就是我的想法。
指向任何类型的所有指针都包含地址,对吧?
假设我声明char *a, b = 'f';
a = &b ;
因此,当我尝试访问 b 的内容时,即 &b,通过指向类型 char.的指针,这没关系。
但是,如果我将 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 = %dn",i ,*b);
}
return 0;
}
现在我认为它只允许读取分配给A的 4 个字节的第一个字节,因为我是通过指向 char 类型的指针访问的,我期望存储高达 255 的值,超出这将有点溢出。
但它发生了一些不同的事情,我只能存储 127 到 -128 whao!.您是否看到它是大小为一个字节的整数类型。您可以运行代码进行查看。
现在假设 int 类型的大小为一个字节
当 a = 256 时,读取的值为 0,这是预期的,因为 0001 0000 0000 它将只读取第一个字节。
输出是可预测的,直到我们达到 a = 127,存储为 0111 1111(从 int 类型的角度来看是正值)当 a = 128 时,输出为 -128,存储为 1000 0000(实际上是 -128)
同样可以解释其他输出 所以输出可以通过假设 int 类型的大小为一个字节来解释
,为什么 printf 这样做而不是抛出错误。
那么printf在这里到底做了什么?
谢谢阁下;)
您的系统使用有符号字符,这是完全正常的。
你似乎假设/期望char
是unsigned
,这并不总是正确的。它要么是有符号的,要么是未签名的,但这取决于实现。
,如果我将 int 数据类型的地址存储在 char 类型的指针中怎么办(尽管我收到警告:来自不兼容的指针类型 [-Wincompatible-指针类型] 的赋值,我没有做错,对吧?我仍在存储一些内存的地址。
是的,你做错了什么,这就是你收到警告的原因。
指针类型很重要,原因有二:
指针算术是根据对象而不是字节完成的。 如果
p
是一个char *
,并且它的值是char
对象的地址(例如0x1000
),则p + 1
计算为下一个char
对象的地址(0x1001
)。 如果p
是一个int *
,并且其值是一个4字节int
对象的地址(0x2000
),则p + 1
计算为下一个4字节int
对象的地址(0x2004
)。与其他类型一样,不同的指针类型可能具有不同的大小和表示形式。
int *
可能具有与char *
不同的表示形式。 在大多数现代系统上,如x86和x86_64它们是相同的,但有一些较旧或古怪的架构并非如此。
所以输出可以通过假设 int 类型的大小为一个字节来解释,为什么 printf 这样做而不是抛出错误。
问题不在于printf
,问题是当您尝试将128
分配给*b
时遇到有符号整数溢出,因为在您的系统上,普通char
占用了[-128..127]
的范围。 不幸的是,有符号整数溢出的行为是未定义的- 不需要您的实现以任何特定方式处理它。 我知道的大多数实现根本不尝试处理它 - 你只是得到一个意想不到的值。 鉴于存在多个有符号整数表示形式,并且许多实现依赖于这种未定义的行为来执行某些优化,因此您可以获得几乎任何结果。