再分享一道笔试题

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;

int main(){

int a[] = {1,2,3,4,5};
int* p = (int*)(&a + 1);

cout << *(a+1) << ',' << *(p-1) << endl;

return 0;
}

问此程序的输出是多少?

错误答案是 2,1

正确答案是 2,5

哎,发现学的多了前面的知识点就忘没了,每天多线程多进程的,却连数组指针都忘记了。

知识点

本题考查的知识点是数组指针,网上的教程和博客通常把数组指针和指针数组一起介绍。我这里也就一起介绍了。

什么是数组指针?

指向数组指针

首先,它是一个指针,指向的对象是数组。我们知道对一个对象取地址,可以得到这种对象类型的指针,因此,题目种对数组 a 取地址(&a)所得到的结果类型就是数组指针。这个数组指针所指向的对象数组的大小是5个int,因此,当这个指针加一的时候指针的偏移量是所指对象的大小(5个int),再将其强制转换为(int*)整型指针并赋值给变量 p ,此时 p - 1指向的就是元素 5 的地址。

image-20220414132405018

那什么是指针数组呢?

元素是指针数组

两者定义方式不同

1
2
3
4
5
// 数组指针
int (*p)[3]; // p 指向一个 包括3个整型数据的 数组

// 指针数组
const char* p[3] = {"wang","guang","xin"}; // 数组 p 包含三个const char* 类型的指针

二者的用途

首先说指针数组,因为这个的用途非常非常常见,毫不夸张地说,我们的每一个程序都显式或隐式的使用了它。😏

那就是主函数参数。

1
2
3
4
int main(int argc,char* argv[]){ 
// 第二个参数就是指针数组 第一个参数是数组的长度
return 0;
}

由于数组在函数传参的过程中会被弱化成指针类型,指针数组也是数组,所以也适用于这条规则,因此主函数的第一个参数传入数组长度。

指针数组在函数传参时会被弱化成二级指针,因此也有下面这种主函数写法。二者是等价的。

1
2
3
int main(int argc,char** argv){
return 0;
}

接下来说一下数组指针的用途,(说实话我也没想到什么场景一定要用数组指针),函数传参时可以使用数组指针。

比如说传递一个二维数组,就可以用传递一个指针的形式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;

void func(int (*p)[2][3]){
cout << "第一行第一个元素:" << (*p)[0][0] << endl;
cout << "第二行第一个元素:" << (*p)[1][0] << endl;
cout << "最后一个元素:" << *((int*)(p+1)-1) << endl;

}

int main(){
int a[][3] = {{1,2,3},{4,5,6}};
func(&a);
return 0;
}

自测题

分别计算下列程序的输出 ,答案在最后

第一题

1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;
int main(){
int a[][3] = {1,2,3,4,5,6};
int* p = (int*)(&a+1);
int* q = (int*)(a+1);
int* r = (int*)a + 1;
cout << *(p-1) << endl << *(q) << endl << *(r) << endl;
return 0;
}

第二题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 64 位
#include <iostream>
using namespace std;

void func(int (*p)[3]){
cout << sizeof(p) << endl;
cout << sizeof(*p) << endl;
cout << sizeof(**p) << endl;
}


int main(){
int a[] = {1,2,3};
func(&a);

return 0;
}

第三题

1
2
3
4
5
6
7
8
9
10
11
12
// 64 位
#include <iostream>
using namespace std;

int main(){
int* a[3] = {0};
cout << sizeof(a) << endl;
cout << sizeof(*a) << endl;
cout << sizeof(**a) << endl;

return 0;
}

答案:

第一题

1
2
3
6
4
2

第二题

1
2
3
8
12
4

第三题

1
2
3
24
8
4

PS:64 位编译器下一个指针 8 个字节,一个 int 4 个字节。

以上答案为 OnlineGDB 的运行结果,不同环境下运行结果可能不同,主要是指针大小的不同。

欢迎留言指出文中错误之处。