这是我编写的一个代码,旨在测试/理解数组中指针的行为。
int main(void){
int a[4];
memset(a, 0, sizeof(a));
printf("%x %x\n",a,&a);
}
Output of the above program on my machine:
bfeed3e8 bfeed3e8
我不明白为什么变量a和&a的值是相同的。据我了解,&a应该给出存储变量a的内存地址。
这种行为的解释是什么?
&a
给你的是a
的地址。而a
给你的是a
,因为它是一个数组,所以会衰变成指向a
的指针。
或者严谨地说,它会衰变成指向a[0]
的指针。
a
衰减和&a
结果之间的区别)在于类型。数组与其第一个元素具有相同的地址,但&a
的类型为int(*)[4]
,而&a[0]
的类型为int*
。 - Steve Jessopa
,那么被推入堆栈的任何内容的类型是什么? - Mr Listera
指定为vararg,则会将int *
放在varargs应该放置的位置(您希望这是堆栈,但请检查平台的ABI)。非常有可能,指向相同地址的两个具有不同类型的指针具有完全相同的表示形式。这实际上并不是标准要求普通对象表示的,尽管对于varargs可能是如此--我不记得是否允许将所有指针varargs读取为void *
,如果是这样,那么即使它们通常不这样,所有指针也必须具有与varargs相同的表示形式。 - Steve Jessopprintf("%x %x\n",a[0],&a);
&a
的类型是int (*) [4]
(指向4个元素的int
数组的指针),并且计算为数组对象的地址;在这方面,指向数组的指针与指向其他任何东西的指针类似。a
。除非它是sizeof
或一元&
运算符的操作数,或者是用于在声明中初始化另一个数组的字符串字面值,类型为“N元素数组的T
” 的表达式将被替换为/转换为/“衰减”为类型为T *
(指向T
的指针),其值是数组中第一个元素的地址。由于数组的地址和数组中第一个元素的地址相同,因此两个表达式都产生相同的value,但它们的types不同。数组的名称也指向它所持有的内存块的起始位置。没什么大不了的。
以下这些都是等价的:
printf("%x\n",a);
printf("%x\n",&a);
printf("%x\n",&a[0]);
a
会衰变为数组第一个字节的地址,而 &a
根据定义是第一个字节的地址。你可能想要在 printf 中使用 *a
或 a[0]
而不是 &a
。数组名"a"指向数组的第一个元素。
为了更好地理解:
*(a + 2) is same with a[2].
在 C 语言中,数组名字,在这个例子中是 a
,被视为一个标签,并代表着数组的地址。对它应用取地址符号(ampersand)会被解释成同样的意思。
函数指针也有类似的问题。如果 func
是一个指向函数的指针,你可以使用 func()
和 (*func)()
来调用该函数。
还有一些间接引用语法的情况,需要特殊处理。
int test[10] = test is pionter as well as &test
如果您想操作除base之外的元素,请使用&test[4]
顺带一提
&test = @test[0] = test
所有指向基本元素的指针