- 论坛徽章:
- 0
|
楼主讲的很清楚了,但篇幅太长,其实总结起来可以很简单的表述:
1、数组名不是指针。数组名代表一个地址,这个地址是数组中第一个元素的地址。
2、指针是一个变量,用来存放地址。
这就是本质的区别。
另外,楼主最后没有说明为什么数组名做为参数传递的时候会变成指针(想当年某高人写的一本xx指南里说数组名做参数时退化成指针,到现在我都还不明白什么叫退化)。
原因其实很简单,在调用一个函数的时候,首先会把传递给该函数的参数压入栈中。用c语言的话来说,就是分配了几个临时变量来存放传递给函数的参数。当参数是个数组名的时候,由于数组名是个地址,什么变量可以存放地址呢?答案当然是指针。所以被调用函数得到的数组名,其实是保存该数组名所代表地址的指针。
下面我举个例子(不熟悉汇编的朋友只要理解上面的文字表述就可以了):
- //c程序
- void test(int a[])
- {
- int *a_prt = a;
- }
- int main()
- {
- int a[3] = {1,2,3};
- test(a);
-
- }
复制代码
部分x86反汇编
- 5 test:
- 6 pushl %ebp
- 7 movl %esp, %ebp
- 8 subl $4, %esp
- 9 movl 8(%ebp), %eax //从%ebp + 8的位置取出值。这里取出的就是下面mian程序中压入的数组第一个元素的地址
- 10 movl %eax, -4(%ebp)
- 11 leave
- 12 ret
- 13 .size test, .-test
- 14 .globl main
- 15 .type main, @function
- 16 main:
- 17 pushl %ebp
- 18 movl %esp, %ebp
- 19 subl $24, %esp
- 20 andl $-16, %esp
- 21 movl $0, %eax
- 22 addl $15, %eax
- 23 addl $15, %eax
- 24 shrl $4, %eax
- 25 sall $4, %eax
- 26 subl %eax, %esp
- 27 movl $1, -24(%ebp) //数组第1元素存在%ebp-24的位置
- 28 movl $2, -20(%ebp) //数组第2素存在%ebp-20位置
- 29 movl $3, -16(%ebp) //数组第3素存在%ebp-16位置
- 30 leal -24(%ebp), %eax //把数组第一个元素的地址(也就是数组名)存入%eax中
- 31 pushl %eax //把%eax中内容压入栈。指针就产生了,压入%eax的这个地址就是test函数参数int a[]的地址,test函数会从这个地址取出数组的地址。
- 32 call test
- 33 addl $4, %esp
- 34 leave
- 35 ret
复制代码 |
|