相信大多数的同学都是第一门能接触到语言是C/C++,其中的指针也是比较让人头疼的部分了,因为光是指针都能专门出一本叫《C和指针》的书籍,足见指针的强大。但如果不慎误用指针,这些指针很大可能就会像恶魔一样把你的程序给直接搞崩溃。
3个月前,我编写了一份这些指针都是恶魔吗?.c的文件,里面从大多数常用的指针类型,一路延伸到纯粹只是在窥探编译器所能产生的恐怖造物,为了增加趣味性,我还把这些指针都划分了段位,只有辨识出该段位绝大多数的指针才能升段。目前看到的同学基本上都分布在青铜到黄金的水平。现在我要将这些恶魔般的指针公诸于世,欢迎大家前来接受挑战自虐。
前置声明:
题目会包括数组、指针、函数,以及它们的各种谜之复合体;
本文后面提及的一些指针不考虑什么实用性,就当做是玩个游戏,但适当情况下会对这些指针做必要讲解;
如果你对指针开始产生不适、恐惧感,建议你提前离开,以免伤到你对C语言的热情;
你想从这些指针里面挑一道作为自己的题目?随你喜欢。
这些指针都是恶魔吗? 青铜(答对所有题升至该段位,正确率100%)请用文字描述下列指针、数组的具体类型:
int * p0; int arr0[10]; int ** p1; int arr1[10][10]; int *** p2; int arr2[10][10][10];下面适当留白以供思考,想好后就可以往下翻看答案。
对于初学C指针的同学基本上应该都能答出来:
int * p0; // p0是 int指针 int arr0[10]; // arr0是 int数组(10元素) int ** p1; // p1是 int二级指针 int arr1[10][10]; // arr1是 int二维数组(10*10元素) int *** p2; // p2是 int三级指针 int arr2[10][10][10]; // arr2是 int三维数组(10*10*10元素) 白银(答对4题升至该段位,正确率80%)请用文字描述下列指针、数组、函数的具体类型:
int (*p3)[10]; int *p4[10]; int *func0(int); int func1(int * p); int func2(int arr[]);这些指针还是比较常见、实用的,想好后就可以往下翻看答案。
int (*p3)[10];中的p3与*先结合,说明p3是一个指针,然后把(*p3)拿开,剩下的就是p3这个指针所指之物(即int[10])。答案:p3是一个指向[int数组(10元素)]的指针,符号化描述即p3是int(*)[10]类型。
int *p4[10];中的p4考虑到优先级,会先与[]先结合,而不是*,说明p4是一个含10元素的数组,然后把p4[10]拿开,则元素类型为int*。答案:p4是一个int指针的数组(10元素),符号化描述即p4是int* [10]类型。
int *func0(int);中的func0先与括号结合,并且括号内仅是形参类型,说明func0是一个函数,返回值类型为int*。答案:f0是函数(形参为int, 返回值为int指针)
int func1(int * p); 答案:func1是 函数(形参为int指针, 返回值为int)
int func2(int arr[]);中,留意int arr[]的写法,仅在函数中才可以这样写,是因为编译器将arr判定为指针类型,即和int * arr的写法是等价的。 答案:func2是 函数(形参为int指针, 返回值为int)
黄金(答对7题升至该段位,正确率70%)请用文字描述下列函数的具体类型。而对于指针,请描述其可读写的情况(可以代码描述):
int func3(int arr[10]); int func4(int *arr[10]); int func5(int(*arr)[10]); int func6(int arr[10][10]); int func7(int arr[][10]); int func8(int **arr); const int * p5; int const * p6; int * const p7; const int * const p8;警告: 到这一步如果你对这些指针已经有所不适的话,建议提前离开,以免你产生了放弃C/C++语言的想法。如果你硬要坚持的话。。。想好后就可以往下翻看答案。
int func3(int arr[10]); 你以为这里int arr[10]就觉得这个函数的形参是一个int[10]那么简单么?那就错了。事实上这里的arr仍然是int *类型!你要想,如果将一个数组按值传递的话就以为着需要拷贝一份数组给该函数用,10个就算了,那int arr[1000000000]呢,一次copy就可以享受爆栈的快乐了。因此这里编译器会将其视作int *类型,并无视掉后面的10,实际上就是将指针按值传递,这样做可以节省大量内存,但多了一层间接性与越界风险(收益远大于风险)。这里的10实际上也仅仅是要提醒作为开发者的你,传入的数组(or指针)必须保证其地址后面sizeof(int) * 10字节都要能够访问。你可以传入元素个数大于等于10的数组,至于小于10的话...后果自负。答案:func3是 函数(形参为int指针, 返回值为int)