先不说啥,上代码,看代码分析。 代码是在VS2015下编译的,
debug 选的64位。所以一个指针占用8个字节。
int main(int argc, char** argv) {
//char ca[6] = { 'a','b','c','d' ,'e'}; int ca[6] = { 1,2,3,4,5 }; printf("-----------------------------\n"); printf("----------主函数-------------\n"); printf("-----------------------------\n"); printf("1. ca=%d\n", ca); printf("2. ca+1=%d\n", ca+1); printf("3. &ca=%d\n", &ca); printf("4. &ca+1=%d\n", &ca+1); printf("5. &(ca[0])=%d\n", &(ca[0])); printf("6. &(ca[1])=%d\n", &(ca[1])); printf("-----------------------------\n"); printf("----------函数调用-----------\n"); printf("-----------------------------\n"); Receive(ca); system("Pause"); return 0; } void Receive(int ca[]) { printf("7. ca=%d\n", ca); printf("8. ca+1=%d\n", ca + 1); printf("9. &ca=%d\n", &ca); printf("10. &ca+1=%d\n", &ca + 1); printf("11. &(ca[0])=%d\n", &(ca[0])); printf("12. &(ca[1])=%d\n", &(ca[1])); }
运行结果如下:这里用%d输出没有用%p,%d对数值来说更直观点。
因为数组是int类型的,数组名为ca,在主函数里面,ca在表达式中代表数组元素的首地址(ca指向一个
int类型,但是这个指向不能改变,ca是数组名是个指针常量),即:ca=&(*(ca+0))=&(ca[0]),所以1和5相等。
ca+1=&(*(ca+1))=&(ca[1])所以2和6相等。
说下2的值:因为ca指向一个int类型,所以步长位sizeof(int)=4,那么ca+1=626455944+4=626455948
重点说下3和4:&ca代表的是不是地址的地址呢?在这里不是。这里涉及到数组名和指针换用问题。在《C专家编程》书中第九章有详细说
在“&ca”中这里的ca不再代表数组的首地址,所以在“&ca”中,ca不再是个地址,所以&ca不是表示地址的地址。
什么时候ca不是再代表数组的首地址呢了?有三种情况:
① 数组作为sizeof()的操作数-显然此时需要整个数组的大小,而不是指针指向的第一个元素大小。
② 使用&在操作符取数组地址(在这里情况)
③ 数组是一个字符串常量初始值
那&ca到底是个什么东西? 这里&ca就是数组的地址。但是&ca和ca有区别。区别就在于:指针类型不一样。ca指向为int类型
&ca指向一个数组。ca→int ; &ca→int (*ca)[](有点像二维数组里面的有木有)。
&ca+1,这里的步长为 数组元素个数*sizeof(int)。4的值=626455944+6*4=626455968
前面是说的是在主函数中,在函数调用的时候又点区别。区别在于&ca变了。
在函数调用是:传的是数组元素的首地址。所以ca在子函数中表示的是地址。那么自然&ca表示的是 地址的地址。所以在这里&ca是个二级指针。
在子函数中&ca值怎么来? 在子函数调用时,系统会在栈中临时开辟空间来存储这个ca的值。所以&ca这个地址存的是ca的值。
为什么&ca的值比其他小呢? 在windows中栈的生长方向是从高到低的。
&ca是个二级指针,所以&ca+1,步长为一个指针占用的空间。这里的debug选得64位,所以一个指针大小位8个字节。
&ca+1=626455904+8=626455912