为什么这有效:
int a = 5;
int *aPtr = &a;
printf("%i", *aPtr);
但这不是:
int a = 5;
int aPtr = &a;
printf("%i", *aPtr);
我不是在寻找它抛出的错误。我试图理解为什么这在概念上不起作用。
答案 0 :(得分:2)
你的例子不起作用,因为:
sizeof(int) == 4; // Bytes (usually)
sizeof(int*) == 8; // Bytes (assuming x86_64)
因此,在分配int aPtr = &a;
时,最重要的4个字节将丢失。
这可以找到(虽然不建议):
#include <stdint.h>
int main()
{
int a = 5;
uint64_t aPtr = (uint64_t)&a;
printf("%i", *(int*)aPtr);
}
答案 1 :(得分:2)
int aPtr = &a;
声明一个名为aPtr
的对象,其类型为int
,因此它不是指针。
更糟糕的是,sizeof(int) != sizeof(int *)
在几个常见平台上(例如自Windows XP以来的所有x64版本的Windows),因此您丢失了指针包含的一些信息,可能会使值存储无用的。
假设它有效,aPtr
仍然是int
类型的对象,因此您无法使用指针间接获取存储在aPtr
地址中的值,意味着表达式*aPtr
将无法编译。没有什么可以阻止你将aPtr
转换为正确的指针类型:
int a = 5;
int aPtr = &a;
printf("%i", *(int *)aPtr);
同样,这假设aPtr
存储了a
的完整地址。无论如何,这只是C的类型安全,这是一件好事(参见上面sizeof(int) != sizeof(int *)
段)。
如果在概念上&#34;&#34;你的意思是&#34;假设地址已正确存储在aPtr
&#34;中,除了它无效的C之外,你的代码没有任何问题,因为以上例子显示。如果地址是0x80,您甚至可以将它存储在一个小的unsigned char
对象中,如果您愿意的话。它存储在内存中的该地址,无论C通过拒绝编译语法无效的代码阻止您使用它。当然,使用正确的变量类型要容易得多,而不是对抗编译器和投射事物。
然后,您可能会问,&#34;如果&a
存储在aPtr
中,为什么编译器无法识别,只需理解*aPtr
就意味着与*&a
相同的事情?&#34;如果这是问题,那么答案很简单:一旦将&a
存储在某种类型T
的对象中,编译器就会理解该对象用于存储类型{{1}的值这就是全部。它不知道它包含一个内存地址,无论你是否在那个对象中存储了一个;它只知道存储在其中的T
类型的值。同样,这只是C型系统按预期工作。
答案 2 :(得分:1)
案例1: -
int a = 5;
int *aPtr = &a; /*this is valid bcz aptr is pointer and it need address and `&a` is valid address*/
printf("%i", *aPtr);/* here you can do *aptr, bcz aptr is pointer and
we can dereference pointer variable */
案例2: - 当您int aptr = &a;
通过编译-Wall
来阅读编译器警告时,它会说明一切。
int a = 5;
int aPtr = &a;/* aptr is normal variable, you are assigning address to it ,but you can't dereference it like *aptr bcz aptr is not pointer */
由于aptr
是普通变量,当你执行*aptr
时,它会引发错误,因为取消引用运算符*
适用于指针变量,而不适用于普通变量。
printf("%i", *aPtr); /* invalid */
答案 3 :(得分:0)
第一个是无效的,因为&amp;是一个需要左值(变量)的一元运算符,不能应用于右值(常量)。
这可以防止第二个因同样的原因而生效。但是假设您用您创建的变量替换了5
:
int a = 5;
int aPtr = &a;
printf("%i", *aPtr);
然后C的静态类型检查会发现aPtr
的类型为int
,a
的类型为int
(因此&a
的类型为{{ 1}}),然后从int*
投射(带警告)&a
到int*
,然后将该地址存储为 int
int
。然后,aPtr
解除引用*
时会遇到错误,因为aPtr
的类型为aPtr
。由于您已从int
投放到int*
,int
现在为aPtr
,而不是int
。
如果你修改如下:
int*
然后它会编译,打印int a = 5;
int aPtr = &a;
printf("%i", aPtr);
的地址(在堆栈上分配的变量),尽管它仍会对从a
到int*
的强制转换发出警告。 / p>
编辑:击败拳头。