C语言基础知识:最核心的—指针!知识总结(第二部分)
指针是C语言最重要也是最难理解的部分,它在我们平时的工作中无处不在。
今天我们继续来看看指针的剩下的知识总结吧!上一批的话可以在主页看到哦~

5 指针与结构体
一个指针,它指向的可以是一个结构体类型,这称为结构体指针。而一个结构体,它的成员中也可以有指针成员。
上面的代码中,定义了一个结构体变量stu1。这个变量中有一个指针变量name。还定义了一个结构体指针pstu。
我们想要通过结构体指针访问结构体成员一般有以下两种方式:
6 指针与const:常量指针与指针常量
初学者常常对这两个概念搞错。首先,我认为需要理解这里说的常量是什么意思。常量就是只可读不可修改的。那常量指针和指针常量到底哪个是只可读不可修改的呢?是指针还是指针指向的内容?这里有一个方法,能让你迅速明白哪个是不可修改的。就是在声明时,以星号(*)为界,分成两部分,星号左边的和星号右边的。const在哪边,那个就是只可读不可修改的。以下面这个代码为例,我们来分析一下:以星号(*)为界,星号左边是char,没有const关键词,所以它指向的内容不是常量。然后,我们看星号的右边是const ptr,所以我们可以说ptr是一个常量。所以,这行代码声明了一个是常量的指针但是指向的内容不是常量。即这个是一个指针常量。
类似的,我们也可以分析下面的代码:
6.1 指针常量(Constant Pointers)
指针常量(Constant Pointers): 它的本质是一个常量,只不过这个常量是指针。由于指针是只可读不可修改的,所以这个指针不能指向别的地址了,但是该地址里的内容还是可以改变的。指针常量的声明格式如下:
我们来看下序:
上面这段程序中:
我们首先定义了两个变量var1,var2;
然后,定义了一个指针常量ptr,并且指向了var1
接着,试图让ptr指向var2
最后,打印出指针ptr指向的地址的内容
让我们来运行一下这个程序:
我们看到这个程序编译报错了:试图对只读(read-only)变量ptr进行赋值。所以,一旦我们定义了指针常量,那这个指针就不能指向其他变量了。
但是我们还是可以修改指向的地址里的内容的:
6.2 常量指针(Pointer to Constants)
常量指针(Pointer to Constants):它的本质是一个指针,只不过它指向的值是常量(只可读,不可修改)。由于指向的是一个只可读不修改的值,所以指针不能通过它存储的地址间接修改这个地址的值,但是这个指针可以指向别的变量。
常量指针的声明格式如下:
还是有一段程序:
我们还是来分析一下这个程序:
我们定义了一个变量 var1,并且初始化为0
然后我们定义了一个指针常量ptr,并且将它指向了var1
接着,试图通过指针ptr来改变var1的值
最后,打印出ptr指向的地址的内容。
我们进行编译:
编译报错也很明显: *ptr是一个只读的。所以不能通过ptr来修改var1的值。
但是,我们可以将ptr指向其他的变量:
6.3 指向常量的常量指针
理解了上面两种类型的话,理解这个就很容易了。指向常量的常量指针是指这个指针既不能指向其他的地址也不能通过地址修改内容。
它的声明格式如下:
同样,下面一段程序,我想你一定知道哪里编译错误了。
编译结果:
7 指针与函数
7.1 函数指针
指针与函数相结合有两种情况:指针函数、函数指针。
指针函数,它的本质是一个函数,它的返回值是一个指针。
函数名本身就是一个指针(地址),这个地址就是函数的入口地址。
输出:
0000000000401550
而函数指针,它的本质是一个指针。只不过它存的地址恰好是一个函数的地址罢了。
函数指针变量定义的格式一般是:
比如:
输出:
可以发现,两者地址相等。
函数指针类型的定义:
比如:
这样的好处就是,首先通过typedef定义一个函数指针类型PSUM,定义完后,PSUM就相当于一种新的类型,可以用此类型去定义其他函数指针变量,就不用每次都使用int(*pSum)(int, int);来定义一个函数指针变量。
输出:
7.2 回调函数
说到函数指针,那还有一个概念不得不提——回调函数。因为在实际的项目代码中实在是太常见了。
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。
那为什么要使用回调函数呢?或者说使用回调函数有什么好处呢?回调函数允许用户把需要调用的方法的指针作为参数传递给一个函数,以便该函数在处理相似的事情时,可以灵活的使用不同的方法。
怎么使用回调函数:
如上述代码:可以看到,Handle()函数里面的参数是一个指针,在main()函数里调用Handle()函数的时候,给它传入了函数Callback_1()/Callback_2()/Callback_3()的函数名,这时候的函数名就是对应函数的指针,也就是说,回调函数其实就是函数指针的一种用法。
8 二维指针
二维指针,或者二级指针。就是指向指针的指针。比如:
输出如下:
从输出结果也可以看到,pa存的内容*pa= 000000000000000A,刚好与a的地址相同。而ppa存的内容*ppa= 000000000061FE14也刚好等于pa的地址。它们之间的内存关系可以用如下的图表示:

8.1 命令行参数
处理命令行参数是指向指针的指针的一个用武之地。
一般main函数具有两个形参。第一个通常称为argc,它表示命令行参数的数目。第2个通常称为argv,它指向一组参数值。由于参数的数目并没有内在的限制,所以argv指向这组参数值(从本质上来说是一个数组)的第一个元素。这些元素的每个都是指向一个参数文本的指针。如果程序需要访问命令行参数,main函数在声明时就要加上这些参数。
举例:
在windows上执行: \test2.exe hello world
输出:
注意,如果命令行中传递的一个参数包括空格,就需要用 ""将参数括起来,比如:
.\test2.exe "hello word"
则上面的代码将输出:
9 结束语
本文关于指针的讲解就结束了。我相信你一定对指针有更深入的了解。
对啦对啦!另外的话为了帮助大家,轻松,高效学习C语言/C++,我给大家分享我收集的资源,从最零基础开始的教程到C语言项目案例,帮助大家在学习C语言的道路上披荆斩棘!可以来我粉丝群领取哦~
微信公众号:C语言编程学习基地
整理分享(多年学习的源码、项目实战视频、项目笔记,基础入门教程)最重要的是你可以在群里面交流提问编程问题哦!
编程学习书籍分享:

粉丝编程交流:
