C - PrintF在这里做了什么?



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

好的,这就是我的想法。
指向任何类型的所有指针都包含地址,对吧?
假设我声明
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在这里到底做了什么?
谢谢阁下;)

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

你似乎假设/期望charunsigned,这并不总是正确的。它要么是有符号的,要么是未签名的,但这取决于实现。

但是

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

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

指针类型很重要,原因有二:

  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它们是相同的,但有一些较旧或古怪的架构并非如此。

所以输出可以通过假设 int 类型的大小为一个字节来解释,为什么 printf 这样做而不是抛出错误。

问题不在于printf,问题是当您尝试将128分配给*b时遇到有符号整数溢出,因为在您的系统上,普通char占用了[-128..127]的范围。 不幸的是,有符号整数溢出的行为是未定义的- 不需要您的实现以任何特定方式处理它。 我知道的大多数实现根本不尝试处理它 - 你只是得到一个意想不到的值。 鉴于存在多个有符号整数表示形式,并且许多实现依赖于这种未定义的行为来执行某些优化,因此您可以获得几乎任何结果。

相关内容

  • 没有找到相关文章

最新更新