为什么这样有效:

int a = 5;
int *aPtr = &a;
printf("%i", *aPtr);


但这不是:

int a = 5;
int aPtr = &a;
printf("%i", *aPtr);


我不是在寻找它引发的错误。我试图了解为什么这从概念上讲是行不通的。

最佳答案

int aPtr = &a;声明一个类型为aPtr的名为int的对象,因此它不是指针。

更糟糕的是,在几个常用平台上(例如,Windows XP之后的所有x64版本的Windows),使用sizeof(int) != sizeof(int *),因此您将丢失指针包含的某些信息,可能会使存储的值无用。

假定它起作用,但是aPtr仍然是int类型的对象,因此您不能使用指针间接获取存储在aPtr地址中的值,这意味着表达式*aPtr将不会编译。没有什么可以阻止您将aPtr强制转换为正确的指针类型:

int a = 5;
int aPtr = &a;
printf("%i", *(int *)aPtr);


同样,这是假定aPtr存储a的完整地址。无论如何,这只是C的类型安全,这是一件好事(请参见上面的sizeof(int) != sizeof(int *)段落)。

如果用“概念上”的意思是“假定地址正确存储在aPtr中”,那么代码就没有什么问题,除了上面的强制转换示例所示,它不是有效的C。如果地址是0x80,则您甚至可以将其存储在一个小的unsigned char对象中。它被存储在内存中的该地址,无论C阻止您通过编译语法上无效的代码来阻止您执行此操作。当然,仅使用适当的变量类型要容易得多,而不是与编译器进行强制转换。

再一次,您可能会问:“如果&a存储在aPtr中,为什么编译器不能识别出并仅仅理解*aPtr*&a相同?”如果这是问题,那么答案很简单:将&a存储在类型为T的对象中后,编译器就会知道该对象用于存储类型为T的值,仅此而已。无论您是否在该对象中存储一个内存,它都不知道它包含一个内存地址。它只知道里面存储着一个T类型的值。同样,这只是C的类型系统按预期工作。

10-05 23:44