C语言进阶——指针与指向函数指针

写在前面:这是一个程序问道者的自我总结,他不相信所谓的权威与官方,只相信自己的验证结果。若有缺陷与不足,欢迎斧正!

指针——C语言的潘多拉之盒

        这是我的恩师朱洪朱先生说过的话,我花了两年的时间去将它理解与消化。先说说在我的母校X电大学,虽然也有开C语言课,但深度之浅,用法之单调,格式之丑陋,没有一项能满足在企业以及学术级要求。如果你在你的大学乃至研究生阶段找到了一个无论在用法、定义或是实用性上都能教的无懈可击的讲师或导师,那么这是你作为学生,一个预备程序员的无上幸运。

        我的文不单是单纯的技术总结,因为这几年我完成了从新手到入门的转变,深知在入门就自学的局限性,也是想为广大程序爱好者们指条路,告诉他们什么是优美的代码,什么是企业级要求,希望能对未来的程序大佬有所帮助。

        说回指针,何谓指针?四字节整型常量?一个函数或变量的首地址?那么问题接踵而来,为什么是常量?首地址是啥意思?我新手听不懂啊。群里的“大佬”动不动就说“cnm你不会百度吗”,每次看见这种我真是深恶痛绝,要是网上有个新手也看的懂的博文我还用你!好了,现在你有了兄弟。

                                                        

        现在我们将此看做一块内存,一个小格子看做2字节(此处考虑到了内存对齐模式,是系统个懒人为了节省控制成本想出的烂招,大部分时候都是牺牲空间提高查找速度),我们默认对齐字节数为2。也就是说当存在结构体时最小分配内存空间为2byte,不懂得朋友可以直接百度内存对齐,看百度百科,写的很详细(内存对齐)。

        然后说回系统视角,这么一堆空间我咋用啊,上面用点下面用点?还是从中间往两边用?不管怎么用,都有一个问题需要解决:我怎么找到这个空间,找到了才有使用一说对不对。好了,那么出现关于指针的第一个概念:地址。下面看一段代码:

#include <stdio.h>

typedef struct test {
	char ch;
	int integar;
	double dou;
}test;

void outHello();
void outHello() {
printf("Hello!");}void main(void) {int num1 = 20;int numSet[20] = {0, 1, 2};test te;printf("这是num1的地址:%d\n", &num1);printf("这是numSet的地址:%d\n", numSet); //这里直接用了数组名,是因为数组名就是其首地址,即可视化的首地址printf("这是te的地址:%d\n", &te);printf("来看看能输出什么 %d\n", outHello);}


        地址,就是以上内存空间的编号,方便系统对其进行使用和分配。也就是说,程序中其实是进行了这样的过程,int num1,C编译环境一看,嗯,int,4字节,值为20!就在内存中给他开辟出一块大小为4b的空间了,所以此时num1值为20,大小为4字节,但不能变来变去啊,这样用的时候计算机多难找,这就是地址都是常量的原因。但既然是4字节,为什么只有一个输出而不是4个呢?&不是取地址符吗,大骗纸~(哭出声)。这就要提到首地址的概念了,如果有几个字节就输出几个字节,那一个大小为300byte的结构体不是要输出300个,很不合理。所以计算机采用首地址的概念,一个首地址“指向”一段空间,敏锐的朋友已经猜到了,这个首地址,就是指针。而我们也看到作为数组的numSet和&numSet的输出完全一致,证实了数组名就是可视化的首地址这一说。函数名同理,对outHello函数名的输出证明了这一点。

 指针基本用法

        指针用起来简单而且随性,想改变一个值我就用指针,要是想改变指针我就用指针的指针。来看一段代码:
#include <stdio.h>

void main(void) {
	int num1 = 20l;
	int *num1Addr = &num1;
	int **num1AddrAddr = &num1Addr;

	printf("*(&num1) %d\n", *(&num1));
	printf("*num1Addr %d\n", *num1Addr);
	printf("**num1AddrAddr %d\n", **num1AddrAddr);
}

高阶用法——指向函数的指针

        这是我觉得C指针最令人着迷的用法。现在看一段代码:
#include <stdio.h>

int add(const int num, const int num1);
void addAndprint(int (*fp)(const int num, const int num2));

void addAndprint(int (*fp)(const int num, const int num2)) {       //此处函数参数含义为:要求参数指向一个函数,该函数返回类型
	int res = 0;                                               //为int,且具有两个类型都为int的参数
	res = (fp)(2, 3);
	printf("res %d\n", res);
}

int add(const int num, const int num1) {
	return num + num1;
}

void main(void) {
	addAndprint(&add);                                            //得到上文addAndprint函数参数,执行
}

        这意味着C语言编程者可以不再只为当下编程了,他可以要求用户提供一个有规定参数与规定返回值的函数,这是“面向未来编程”,实现机理某种程度上与Java的接口是一样的,大大提高了C的灵活度。

扫描二维码关注公众号,回复: 8801113 查看本文章

        C作为万语言之母是有其原因的,他将手伸到了计算机底层,告诉程序员们什么能做什么不能做,也使之十分适合验证一些数据结构,他的指针、“面向未来编程”,都是Java的相关知识,希望你能珍视这门语言,握紧这把钥匙开始THE DOOR of CODE。

发布了29 篇原创文章 · 获赞 0 · 访问量 3316

猜你喜欢

转载自blog.csdn.net/smithlaod/article/details/79802889