指针变量的大小存储在哪里?

时间:2011-08-26 07:04:06

标签: c arrays pointers

 #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是不同的情况。只有地址存储在指针变量中才是真的吗?有关指针变量的元数据存储在哪里?

5 个答案:

答案 0 :(得分:2)

由于您的变量声明int a[5] = ...,编译器知道a的类型为int [5](因此,sizeof(a)将返回20)。由于编译器知道a的类型,因此获取a的地址将产生正确类型的指针。这可能有点令人惊讶:&a不会产生int**而是产生int (*)[5](指向五个整数数组的指针)。

所以执行时

int *ptr=(int*)(&a+1);

你取a的地址,添加一个(由于C / C ++指针算术的工作方式,将指针引用的地址增加sizeof(a)字节),然后转换结果到一个int。所以在这一点上,ptr指向数组的最后一个元素(偏移量为20)。

然后将指针转换为int*并使用*(ptr-1),因此您取消引用偏移量16处的int值 - 这恰好是最后一个数组元素的位置。

答案 1 :(得分:1)

它不会被存储。编译器在编译代码时当然需要跟踪它,但在此之后,它基本上只是硬编码到生成的指令中。

答案 2 :(得分:0)

&amp; a属于int (*)[5]类型,即&amp; a是指向数组的指针,而不是指向int的指针。编译器(显然)知道数组大小是什么,并将其用于指针算法。

答案 3 :(得分:0)

指针具有“双重类型”。一方面,它是一个具有自己大小的指针(假设某些系统上每个指针都有4个字节)。另一方面,它是指向具有大小(除void *之外)的东西的指针。

一般来说类型不能直接在C中访问。你不能问“变量的类型是什么”。

但是大小始终可以通过sizeof访问。所以int *本身可能使用4个字节,但编译器知道它指向一个整数,并且它知道整数的大小。 对于struct xyz *,指针本身可能再次是4个字节,但编译器知道它指向一个结构,并且它知道结构的大小。重要的是指针的类型超出“指针”。

因此,如果您定义struct xyz *ptr,则可以通过选中sizeof(*ptr)来确定指针所指向的大小。即使ptr未初始化,您也可以这样做。

唯一不能做的是在sizeof(*ptr)定义ptr后检查void *

就“元数据”而言,它都是指针类型。

答案 4 :(得分:0)

指针只是一个内存地址,没有元数据。将N添加到类型T *的指针会导致将N * sizeof(T)添加到地址值。编译器在编译期间知道每种类型的大小,不存储任何内容。

  • a+1指向a中的第二个int,因为它将a视为int*,即指向第一个元素的指针,即sizeof(int)被添加到内存地址
  • &a+1指向“second int [5] array”,即sizeof(int [5])被添加到内存地址
  • ptr-1指向“第二个数组”的第一个元素之前的int,即a的最后一个元素。