数组名的意义:
1. sizeof( 数组名 ) ,这里的数组名表示整个数组,计算的是整个数组的大小。
2. & 数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表示首元素的地址。
下面我们来看几道经典的面试题
1
int main()
{int a[5] = { 1, 2, 3, 4, 5 };int *ptr = (int *)(&a + 1);printf( "%d,%d", *(a + 1), *(ptr - 1));return 0;
}
我们首先要知道此处的(&a + 1)是什么——&a是取出整个数组的地址,原本ptr是指向1的地址,再给它+1就表示跳过这个数组,即
(a+1)此处a表示首元素地址,+1表示第二个元素地址,所以*(a + 1)就是第二个元素,即2;
*(ptr-1)就是指向5的地址,再解引用就是5;所以这道题答案是 2,5;
2
int main()
{int a[4] = { 1, 2, 3, 4 };int *ptr1 = (int *)(&a + 1);int *ptr2 = (int *)((int)a + 1);printf( "%x,%x", ptr1[-1], *ptr2);return 0;
}
int * ptr1 = ( int * )( & a + 1 );这里的 &a表示取出整个数组的地址,ptr1指向1的地址,+1跳过整个数组即指向4后面的地址,即
ptr1[-1]等价于*(ptr1-1)即是指向4再解引用就是4;
int * ptr2 = ( int * )(( int ) a + 1 );这里的a代表首元素地址,给其强制类型转化成int 再+1,即只跳过了int类型中的1个字节,整型在内存中是小端存储,即1,2,3,4原本在内存中应该是以0x00000001,0x00000002,0x00000003,0x00000004的形式存储,它们以小端存储即
,所以对ptr解引用*ptr=02000000,以%x的形式打印出来省去前面的0,结果应该是2000000;
这道题答案是4,2000000;
3
#include <stdio.h>
int main()
{int a[3][2] = { (0, 1), (2, 3), (4, 5) };int *p;p = a[0];printf( "%d", p[0]);return 0;
}
a是一个三行两列对的二维数组,注意此处对二维数组的初始化, int a[3][2] = { (0, 1), (2, 3), (4, 5) };,他们中间是用“ ,”隔开,不是“ {}”,所以,他只初始化了3个元素,即1,3,5,剩下的全是0,即这个二维数组应该是
p = a[0];a[0]表示的是&a[0][0], p就指向1的地址,p[0]表示*(p+0)就是*p就是1;
4
int main()
{int a[5][5];int(*p)[4];p = a;printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);return 0;
}
a是int(*)[5]类型,p是int(*)[4]类型,如图所示
& p [ 4 ][ 2 ] - & a [ 4 ][ 2 ],就是他们中间有几个元素,如图,结果是-4,分别以%p和%d形式打印,就是
FFFFFFFC和-4
5
int main()
{int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int *ptr1 = (int *)(&aa + 1);int *ptr2 = (int *)(*(aa + 1));printf( "%d,%d", *(ptr1 - 1), *(ptr2 - 1));return 0;
}
int * ptr1 = ( int * )( & aa + 1 );&aa表示整个二维数组的地址,指向1,+1表示跳过整个数组,指向第10后面的地址,*(ptr1-1)就是指向10的位置解引用就是10;
int * ptr2 = ( int * )( * ( aa + 1 ));aa表示二维数组首元素地址即是第一行的地址指向1,+1表示跳过第一行指向第二行首元素的地址6,*(ptr2-1)就是指向5的位置,解引用就是5.
所以这道题答案是10,5