数组名与地址
前言
实验环境windows 10 vs2017
设一维数组int a[10]={1,2,3,4,5,6,7,8,9,10}:
a 被解释为数组的第一个元素的地址, &a 则是得到的整个数组的地址。
- 如有以下操作:
int *p = a;
cout << "指针P的值为:" << p << endl;
cout << "数组a的地址是:" << &a << endl;
- 输出结果:
输出的结果虽然相同,但是代表的意义却不一样。从概念来看a=*(&a[0])
是一个 4字节大小的内存的地址,但是&a 却是整个数组大小字节内存的地址 精确到a[10]数组sizeof(&a)=4*10;
- 如果有以下操作
int *p=a;
p++;
cout << *p;
- 结果为:
- 由上文一可知 p的值为a[0]所在内存的地址,*p则是对指针解除引用(也就是输出地址所 在的值),p++是什么?地址加一,即代表指针移动4个字节。如果是double类型则移 动八个字节 ,即a[1]所对应的。由此可以得出两个重要公式:
a[i]=\*(p+i);
&a[i]=p+i;
- 如果有一个二维数组
int b[10][10]={1,2,3,4,5,6,7,8,9,10,11……}:
由上文可知 &a代表整个数组的地址。二维数组则是由N个一维数组构成的 如数组b则是由10个数组a构成的。由此得出一个重要结论。
int (p)[10]=&b[N];
整个拆开来看这个公式 等号右边是&b[N] ,由上文可知 &a 是整个一维数组,推导到二维数组 &b[0]即代表 二维数组整个第一行的地址, &b[N] 即代表第N-1行(在c++中数组中 数组下标从0开始)的地址。再来看等号的左边 Int (*p)[10] :一个int 类型指针p,指向包含10个元素的数组。(注意和int *p[10]区分。*p[10]:有10个int类型的指针) - 如有以下操作
int (*p)[10] = &b[1];
cout << p << endl;
cout << *p << endl;
cout << **p << endl;
cout << sizeof(p) << endl;
cout << sizeof(*p) << endl;
- 结果为:
- 根据上文很容易知道p的地址是二维数组整个第二行地址(如果对这里感到疑惑,再从头 读上一段),*p=&b[1]; 现在想如果要输出第二行第一个元素的值怎么办?我们可以直 接用数组名加下标:
cout << b[1][0]
。如果用指针p表示呢?现在我们已知*p=&b[1] ,所以可以推出b[1]=*(&b[1])=*(*p)。又因为不带&的b[1]地址表示第一个元素的地址,所以饶了这么一大圈 b[1][0]=*(*P).
- 如有以下操作:
int (*p)[10] = &b[0];
现在用指针p输出b[3][2]的值怎么做?
首先第一步由题意可知,指针p的值为整个第一行的地址。而我们是想输出第四行的某个值,先把p指到第四行。由上文二可知:如果p+1,实际上指针将移动4*10个字节,也就是&b[1],移动到第四行即p+3;。如果现在输出*(p+3),将输出整个第四行的地址。题意要求输出b[3][2]的值。联系上文一和四,如果输出*(*(P+3))将输出b[3][0]的值,我们只需将指针指向b[3][0],然后指针加2,即向右移动4*2个字节,即是b[3][2]的值。b[3][2]=((p+3)+2);当int (*p)[10] = &b[0]时,可推导出最最重要的一个结论:
b[i][j]=*(*(p+i)+j);