您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center 汽车系统工程   模型库  
会员   
   
LLM大模型与智能体开发实战
2026年1月17、24日 北京+线上
需求分析与管理
2026年1月22-23日 北京+线上
UAF与企业架构
2026年2月3-4日 北京+线上
     
   
 订阅
C语言指针:如何区分指针函数、函数指针、指针数组、常量指针等概念
 
作者:嵌入式电子学习
  166   次浏览      8 次
 2025-12-17
 
编辑推荐:
本文介绍了如何区分C语言中的指针函数、函数指针、指针数组、二级指针、常量指针、指针常量等常见指针概念相关内容。 希望能为大家提供一些参考或帮助。
文章来自于微信公众号嵌入式电子学习,由火龙果Linda编辑推荐。

C语言指针

如何区分C语言中的指针函数、函数指针、指针数组、二级指针、常量指针、指针常量等常见指针概念。

1.核心内容

1.1、符号优先级

从名字开始,按符号的优先级进行结合

1.名字和定义方式

int a;

• 表示a是“整型变量”

int *p;

• 表示p是“(指向)整型指针”,p指向整型变量,*p就是整型变量

int a[5];

• 表示a是“整型数组”,数组元素都是整型变量,a也是指针,是指向整形变量的指针,a[0]则是整形变量,*a等价于a[0],*a也是整形变量

2.符号结合的优先级

• 表示是数组的 [ ] > 表示是指针的 *

• 表示是函数的 () > 表示是指针的 *

1.2、例子分析

1. int p;

• 定义了一个整型的变量p

2. int *p;

• 从名字开始看,名字是p;

• 先和*结合,表示p是指针;

• 再和int结合,表示指针指向整型变量。

• p是一个指向整型变量的指针即“整型指针”

3. int p[5];

• 从名字开始看,名字是p;

• 先和[]结合,p是数组;

• 再和int结合,数组的组成元素(单元)是整型变量。

• p是一个由整型变量组成的数组(整型数组)

4. int *p[2];

• 从名字开始看,名字是p;

• 先和[]结合,p是一个数组;

• 再和*结合,数组元素是指针类型;

• 再和int结合,指针指向整型(整型指针);

• p是一个由(指向)整型(的)指针变量组成的数组

5. int (*p)[2];

• 从名字来看,名字是p;

• 先和*结合 —— p是一个指针;

• 再和[]结合 —— 指针指向数组;

• 再和int结合 —— 数组元素都是整型;

• p是一个指向整形数组的指针

6. int **p;

• 从名字来看,名字是p;

• 先和一个*结合,p是一个指针;

• 再和另一个*结合, 指针指向指针;

• 再和int结合,被指向的这个指针是指向整型的指针(整型指针);

• p是一个指向整型指针的指针(二级指针)

7. int p(int);

• 从名字来看,名字是p;

• 先和表示函数的(int)结合,p是一个函数;

• 进入()是int,函数需要一个int型参数;

• 再和外面的int结合,函数的返回值是一个整型量;

• p是一个“需要整型作为参数,返回值是整型量”的函数

8. int (*p)(int);

• 从名字来看,名字是p;

• 先和*结合,p是一个指针;

• 再和表示函数的(int)结合,指针指向函数;

• 进入()是int,函数需要一个int型参数;

• 再和外面的int结合,函数的返回值是整型;

• p是一个指向“需要整型作为参数,返回值是整型量的函数”的指针

9. int *p(int);

• 从名字来看,名字是p;

• 先和(int)结合,p是一个函数;

• 再和*结合,函数的返回值是一个指针;

• 再和int结合,指针指向整型量;

• p是一个“需要整型作为参数,返回值是指向整型的指针”的函数

10. int p(int)[2];

• 从名字来看,名字是p;

• 先和(int)结合,p是一个函数;

• 再和[]结合,函数返回值是数组;

• 再和int结合,数组元素是整型;

• p是一个“参数是整型,返回值是整型数组”的函数

11. int (*p(int))[2];

• 从名字来看,名字是p;

• 先和(int)结合,p是一个函数;

• 再和*结合,函数返回值是指针;

• 再和[]结合,指针指向数组;

• 再和外面的int结合,数组元素是整型;

• p是一个“需要整型作为参数,返回值是指向整型数组的指针”的函数

12. int *(*p)[2];

• 从名字来看,名字是p;

• 先和*结合,p是一个指针;

• 再和[2]结合,指针指向数组;

• 再和*结合,数组元素是指针类型;

• 再和int结合,指针指向整型(即数组元素是整型指针);

• p是一个指向 “ 由整型指针变量构成 的数组 ” 的指针

13. int *(*p(int))[2];

• 从名字来看,名字是p;

• 先和(int)结合,p是一个函数;

• 再和*结合,函数返回值是指针;

• 再和[]结合,指针指向数组;

• 再和外面*结合,数组元素是指针变量;

• 再和外侧int结合,指针指向整型变量;

• p是一个“参数是整型,返回值是指向 由整型指针变量构成的数组 的指针”的函数

2.指针和内存(本质)

指针是模具

• 任何一种数据类型我们都可以把它当一个模子

• 一个int *类型的模子在内存上切出了4个字节的空间,然后把这个4个字节大小的空间命名为p,同时限定这4个字节的空间里面只能存储某个内存地址,即使你存入别的任何数据,都将被当作地址处理,而且这个内存地址开始的连续4个字节上只能存储某个 int类型的数据。

• 把 p 称为指针变量,p 里存储的内存地址处的内存称为 p 所指向的内存。指针变量 p 里存储的任何数据都将被当作地址来处理。

• 一个基本的数据类型(包括结构体等自定义类型)加上*号就构成了一个指针类型的模子。这个模子的大小是一定的,与*号前面的数据类型无关。*号前面的数据类型只是说明指针所指向的内存里存储的数据类型。所以,在 32 位系统下,不管什么样的指针类型,其大小都为 4byte。可以测试一下sizeof(void *)。

指针和内存

• 指针自身的值——是地址,表示的是内存区域;

• 指针指向的值——是这个地址(内存区域)上存的数据;

• 指针所指向的内存区域就是从指针所代表的的那个内存地址开始,长度sizeof(指针所指向的类型)的一片区域。

• 我们说一个指针值是XX,就相当于说该指针指向了以XX为首地址的一片内存区域。

• 我们说一个指针指向了某块区域,就相当于说该指针的值是这个内存区域的首地址。

• 指针本身所占据的内存区:在32位平台里,指针本身占据了4个字节。

3.指针的运算

3.1、指针的算数运算

• 指针可以加上或减去一个整数——是以单元为单位进行的加减

• 两个指针不能进行加法运算;

• 两个指针可以进行减法,但必须类型相同(一般用在数组方面);

char a[20]="You_are_a_girl";
char
 *p=a;
char
 **ptr=&p;
printf
("**ptr=c%\n",**ptr);
ptr++;
printf
("**ptr=c%\n",**ptr);

分析

• p是指向char的指针;

• ptr是二级指针,指向的是一个指针;

• 当p+1时,内存地址移动的是size(char)=1个字节的位置,刚好一到a[1]的地址上;

• 当ptr+1时,内存地址移动的是size(p)=4个字节的位置。注意!这是ptr移动了四个字节的位置,无法知道移动到哪了(如果是p移动4个字节的位置,那就是到了a[3]的位置了),所以说,【ptr移动了四个字节的位置】实际上是跑飞了。二级指针移动出错容易使程序跑飞。

总结

• 一个指针ptrold 加(减去)一个整数n后,结果是一个新的指针ptrnew,ptrnew的类型和ptrold的类型相同,ptrnew所指向的类型和ptrold所指向的类型也相同。

• ptrnew的值将比ptrold的值增加(减少) n * sizeof(ptrold所指向的类型)个字节!也就是移动了n个他所指向的数据类型的空间,就像数组那样的移动和访问。

3.2、指针运算:* 和 &

*p的结果就是p所指向的东西:*p的类型是p指向的类型,*p占用的地址是p所指向的地址。

int a=12,b;//整型
int
 *p;//指针变量
int
 **ptr;//二级指针

• 定义整形变量、指针变量、二级指针变量

p=&a;

• p是指针变量,取出a的地址然后赋值给p

*p=24;

• *p表示p指向的值a,相当于把a赋值为24

ptr=&p;

• 左边是二级指针,右边是取出指针的地址

*ptr=&b;

• *ptr表示ptr指向的类型,即一级指针p,左边是一级指针,右边是一级地址

**ptr=34;

• ptr是二级指针,**ptr表示二级指针取两次地址就成了对应的数据类型即int型变量,右边是整型34

4.数组和指针

数组的数组名可以看做一个指针。

char *str[3]={ "hello", "goodmorning", "world"};

• str先与[]结合,表示str是数组;

• 再与*结合,表示数组元素是指针类型;

• 再与char结合,表示指针是char型指针;

• str是一个“由char型指针组成的”数组

• 而字符串相当于是一个数组,在内存中以数组的形式储存,只不过字符串是一个数组常量,内容不可更改。如果看成指针的话,他是常量指针,也是指针常量。

• 常量指针:类比整形指针的说法,表示指向常量的指针,因此*p等同于常量类型const,无法对*p赋值【*p=2这种语句是错误的】。

• 指针常量:类比整形常量的说法,表示这个指针变量的值(即地址)是常量不可修改的,因此,p等同于常量类型,p的值是不可修改的,无法对p进行赋值【p=0x08000000这种语句是错误的】。

数组元素是指针,那么数组名显然就要成为了二级指针,即指向了指针。

str[0]=*str;

• str是二级指针,*str表示str所指向的那个指针

str[1]=*(str+1);

• 1移动的就是1个 char* 类型的长度,即移动1个所指类型,指针变量char*占据4个字节

str[2]=*(str+2);

• 2移动的就是2个 char* 类型的长度,即移动2个所指类型,指针变量char*占据4个字节

• str+1是一个二级指针,指向数组的第1号单元,即"goodmorning"的地址

• *(str+1)是一个一级指针,指向"goodmorning"的第一个字符"g"

 

   
166   次浏览       8 次
相关文章

深度解析:清理烂代码
如何编写出拥抱变化的代码
重构-使代码更简洁优美
团队项目开发"编码规范"系列文章
相关文档

重构-改善既有代码的设计
软件重构v2
代码整洁之道
高质量编程规范
相关课程

基于HTML5客户端、Web端的应用开发
HTML 5+CSS 开发
嵌入式C高质量编程
C++高级编程

最新活动计划
企业架构助力业务与IT协作 1-17[在线]
LLM大模型与智能体开发实战 1-17[在线]
AI大模型编写高质量代码 1-14[在线]
AI原生应用的微服务架构 1-22[在线]
需求分析与管理 1-22[北京]
视觉大模型及其应用 1-30[在线]
UAF与企业架构 2-3[北京]
 
 
最新文章
.NET Core 3.0 正式公布:新特性详细解读
.NET Core部署中你不了解的框架依赖与独立部署
C# event线程安全
简析 .NET Core 构成体系
C#技术漫谈之垃圾回收机制(GC)
最新课程
.Net应用开发
C#高级开发技术
.NET 架构设计与调试优化
ASP.NET Core Web 开发
ASP.Net MVC框架原理与应用开发
成功案例
航天科工集团子公司 DotNet企业级应用设计与开发
日照港集 .NET Framewor
神华信 .NET单元测试
台达电子 .NET程序设计与开发
神华信息 .NET单元测试