- #include <stdio.h>
- int main(char argc,char **argv){
- int a[10];
- printf("%p\n",a);
- printf("%p\n",&a);
- printf("%p\n",&a[0]);
- int b[10][10];
- printf("%p\n",b[0]);
- printf("%p\n",&b[0]);
- printf("%p\n",&b[0][0]);
- printf("%p - %p\n",a,a+1);
- printf("%p - %p\n",&a,&a+1);
- printf("%p - %p\n",b[0],b[0]+1);
- printf("%p - %p\n",&b[0],&b[0]+1);
- return 0;
- }
- .file "test.c"
- .section .rodata
- .LC0:
- .string "%p\n"
- .LC1:
- .string "%p - %p\n"
- .text
- .globl main
- .type main, @function
- main:
- pushl %ebp
- movl %esp, %ebp
- andl $-16, %esp
- subl $480, %esp
- movl 8(%ebp), %eax
- movb %al, 28(%esp)
- movl $.LC0, %eax
- leal 440(%esp), %edx
- movl %edx, 4(%esp)
- movl %eax, (%esp)
- call printf
- movl $.LC0, %eax
- leal 440(%esp), %edx
- movl %edx, 4(%esp)
- movl %eax, (%esp)
- call printf
- movl $.LC0, %eax
- leal 440(%esp), %edx
- movl %edx, 4(%esp)
- movl %eax, (%esp)
- call printf
- leal 40(%esp), %edx
- movl $.LC0, %eax
- movl %edx, 4(%esp)
- movl %eax, (%esp)
- call printf
- movl $.LC0, %eax
- leal 40(%esp), %edx
- movl %edx, 4(%esp)
- movl %eax, (%esp)
- call printf
- leal 40(%esp), %edx
- movl $.LC0, %eax
- movl %edx, 4(%esp)
- movl %eax, (%esp)
- call printf
- movl $.LC1, %eax
- leal 440(%esp), %edx
- addl $4, %edx
- movl %edx, 8(%esp)
- leal 440(%esp), %edx
- movl %edx, 4(%esp)
- movl %eax, (%esp)
- call printf
- leal 440(%esp), %eax
- addl $40, %eax
- movl $.LC1, %edx
- movl %eax, 8(%esp)
- leal 440(%esp), %eax
- movl %eax, 4(%esp)
- movl %edx, (%esp)
- call printf
- leal 40(%esp), %eax
- leal 4(%eax), %ecx
- leal 40(%esp), %edx
- movl $.LC1, %eax
- movl %ecx, 8(%esp)
- movl %edx, 4(%esp)
- movl %eax, (%esp)
- call printf
- movl $.LC1, %eax
- leal 40(%esp), %edx
- addl $40, %edx
- movl %edx, 8(%esp)
- leal 40(%esp), %edx
- movl %edx, 4(%esp)
- movl %eax, (%esp)
- call printf
- movl $0, %eax
- leave
- ret
- .size main, .-main
- .ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
- .section .note.GNU-stack,"",@progbits
同过上面的C代码和编译成汇编语言对比,可以看出,数组名a和&a,&a[0]的值都是440(%esp)里面的东西,也就是他们的地址是相同的.尽管如此,意义上却是两种东西,通过代码printf("%p - %p\n",a,a+1);和printf("%p - %p\n",&a,&a+1);打印出来的值可以看出,他们两者之间的数据长度有差异,也就是指向的数据类型根本不一样!
引用网上的一段话:
比如:
对数组名取地址在C标准里面是未定义的行为。由于数组名是右值,而&操作符要求操作数具有具体的内存空间,换言之就是一个变量,因此对数组名取地址本来就是非法的,早期的编译器明确规定这是非法的。不过不知道什么原因,现在的编译器多数把&array定义为一个值跟array相同,类型是一个指向数组的地址,注意了,是地址,不是指针。之所以是指向数组的地址,是因为array是一个数组名,它就代表了int array[10]这个数组。而ptr也是定义为一个指向具有10个int数的数组的指针,因此&array能被赋予ptr.也就是说数组名永远都不会是指针.
总结一下:在C里面,数组名只是一个单纯的地标标号(地址),它代表着该数组的首个元素的地址.一般情况下,他可以使用指针的方式访问数组成员.但是,如果对数组名进行取址操作(&),那么(&)表达式将返回一个指针变量,该指针指向一个数组类型对象,如果对该指针进行运算操作,那么他的偏移大小将是一个sizeof(数组对象).
阅读(904) | 评论(2) | 转发(1) |