指针变量的大小被存储在哪里?
#include <stdio.h>
int main(void)
{
int a[5]={1,2,3,4,5};
int *ptr=(int*)(&a+1);
printf("%d %d\n",*(a+1),*(ptr-1));
return 0;
}
2 5
在这里,在声明*ptr= (int*)(&a+1)
1不添加到&a
。其实它就像&a + sizeof(a)
。现在我的问题是存储指针变量的大小,还是没有存储指针变量的大小,然后如何计算。在int, float, char
等的情况下,它们的大小是在编译器中预定义的,所以int *a
是不同的情况。是不是真的只有地址存储在指针变量中没有其他的东西?关于指针变量的元数据被存储在哪里?
它没有被存储。编译器在编译代码时肯定需要跟踪它,但在此之后,它基本上只是硬编码到生成的指令中。
由于您的变量声明int a[5] = ...
,编译器知道a
类型为int [5]
(因此,sizeof(a)
将返回20)。由于编译器知道a
的类型,因此获取a
的地址将产生正确类型的指针。这可能有点令人惊讶:&a
不会产生int**
,而是产生int (*)[5]
(指向由5个整数组成的数组的指针)。执行
int *ptr=(int*)(&a+1);
当你的a
地址
所以,添加一个(其中,由于方式的C/C++指针算术工作,通过sizeof(a)
字节增加了由指针所引用的地址),然后将结果转换为int。因此,在这一点上,ptr
指向数组最后一个元素后面(偏移20处)。
然后,您将指针指向int*
并使用*(ptr-1)
,因此您将偏移量为16的int值取消引用 - 这恰好是最后一个数组元素所在的位置。
&一个IS int (*)[5]
类型,即,一个&是一个指针数组,不是指针为int。编译器知道(明显)数组的大小,并将其用于指针运算。
指针具有“双重类型”。一方面,它是一个具有自己大小的指针(假设某些系统上的每个指针有4个字节)。另一方面,它是指向具有大小的指针(除了void *
之外)。
类型通常不能直接在C中访问。您不能问“变量的类型是什么”。
但大小总是可以通过sizeof
访问。因此int *
本身可能使用4个字节,但编译器知道它指向一个整数,并且它知道整数的大小。 对于struct xyz *
,指针本身可能再次是4个字节,但编译器知道它指向一个结构,并知道结构的大小。重要的是指针的类型超出了“指针”的范围。
所以,如果你定义了struct xyz *ptr
,你总是可以通过检查sizeof(*ptr)
找出指针指向的大小。即使ptr
未初始化,也可以这样做。
您唯一不能做的事情是在ptr
定义为void *
时检查sizeof(*ptr)
。
就“元数据”而言,它都是指针的类型。
指针只是一个内存地址,没有元数据。将N添加到类型T *的指针会导致将N * sizeof(T)添加到地址值。编译器在编译期间知道每种类型的大小,不存储任何内容。
-
a+1
指向一个第二int
,因为它把a
作为int*
即指针的第一个元素,即的sizeof(int)的被添加到存储器地址 -
&a+1
点于“第二INT [5]数组“,即sizeof(int [5])被添加到内存地址 -
ptr-1
指向在”第二个数组“的第一个元素之前的int
,即a的最后一个元素。
重复:http://stackoverflow.com/questions/7194388/using-pointers-in-c – phoxis