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