数组名取地址是二重指针吗?还不一重指针?具体的原理是什么?

void BOOTLOADER_SECTION boot_program_page (u4 page, uint8_t *buf){}

//放到这个函数的第二个参数,为什么可以是:(u1 *)&BootBuffer(即数组名取地址,再强制转换为指针)

数组名仅仅是“相当”于指针,而并非真的是指针,数组名是只是个常量(一个值为数组首元素地址的常量)。
而之所以有&BootBuffer,其实这里的BootBuffer的意义早已经不是当初那个数组名了,它此时代表了整个数组。

其实BootBuffer和 &BootBuffer结果都是数组的首地址,但他们的类型是不一样。
1. BootBuffer表示&BootBuffer[0],也即对数组首元素取地址,BootBuffer+1表示首地址+sizeof(元素类型)。
2. &BootBuffer虽然值为数组首元素地址,但类型为:类型 (*)[数组元素个数],所以&BootBuffer+1大小为:首地址+sizeof(BootBuffer)。

所以最后对&BootBuffer要有强制类型转换(u1 *),即转换为类型为u1的指针,保证和函数的输入参数类型一致。

PS:如果不好理解,试一下这段代码就明白了:
#include<stdio.h>
int main()
{
int BootBuffer[10];

printf("BootBuffer:\t%p\n", BootBuffer);
printf("&BootBuffer:\t%p\n", &BootBuffer);
printf("BootBuffer+1:\t%p\n", BootBuffer+1);
printf("&BootBuffer+1:\t%p\n", &BootBuffer+1);

return 0;
}
BootBuffer+1是一个元素的内存大小(int类型,增加4),而&BootBuffer+1增加的是整个数组的内存大小(10个int类型,增加40,即十六进制0x28)。既BootBuffer和&BootBuffer的指向和&BootBuffer[0]是相同的,但性质不同!追问

那(u1 *)&BootBuffer这样可以当成,一个指向数组首地址的指针变量用吗?(也就是可以当成一个指针变量用?)还是,BootBuffer与&BootBuffer一样的,只有++时有差别?

追答

可以当做一个指向数组首地址(且数组元素类型是u1)的指针变量用

追问

那当作参数传递给uint8_t *buf之后,再uint8_t w = *buf++; w等于首元素值?

追答

如果u1和uint8_t的定义一样,那么这样调用并在函数中这样赋值后w是首元素值。我建议有不明白的可以把这部分程序拷出来,单独后在程序中加输出语句试一下,实践出真知。

温馨提示:答案为网友推荐,仅供参考
第1个回答  2014-07-21
数组名做为参数传递时,无论是加&还是不加,其到子函数中时,都是地址值(数组首地址),具体这个地址值如何解释,可以由子函数来确定
第2个回答  2014-07-21

首先,数组名取地址,它的可以进行二次*操作,从这点来看,它有点像二重指针,但是,编译器对它的解析却是跟二重指针的解析是完全不一样的。例如下面的代码:

int a[2];
int ** pa = (int**)&a;

如果你这样做,然后对pa进行**pa操作会发现,你悲剧了,但是**(&a)却是OK的。这是因为数组名,是一个地址,但不能跟一般的指针完全等价,而且是const的,编译器对它的解析完全不一样。

追问

那(int*)&a是什么意思?

追答

如果是传参参xx fun(int* p)这样的函数的参数,直接传a就可以了,不需要(int*)&a。
另外,&a的值跟a的值(抛开类型)是一样的值,你可以试一下:((void*)&a == (void*)a)

追问

是直接传A就可以了,但是有些人写代码就是(int*)&a。我想知道其中的区别。

追答

只能说,没必要。但另一种倒比较常用 &a[0]