当前位置: 首页 > news >正文

数组指针、指针数组、常量指针、指针常量、函数指针、指针函数

在C语言中,常常有一些相似的名词出现,但其实代表的是不同的含义。本文仅阐述自己对这些概念的理解和分享。

1.数组指针与指针数组的异同点

2.常量指针和指针常量的异同点

3.函数指针和指针函数的异同点

接下来我将用一段程序来说明这6者之间的关系,示例程序已在visual studio中验证完成并附在文末。

//数组指针:指向数组的指针 int(*ptr)[5]
//指针数组:一个数组,元素都是指针 int *arr[5]
//常量指针:指向常量的指针,指向内容是常量,内容无法修改,地址可以修改 const int *ptr
//指针常量:指针本身是常量,指向不能改变,可以修改内容,地址无法修改 int *const ptr
//函数指针:指向函数的指针,通过调用该指针来使用该函数,返回类型(*函数名)(参数列表)
//指针函数:返回指针的函数,返回类型 *函数名 (参数列表)

 

数组指针:是一个指向整个数组大小的指针;对指针进行加减运算时,移动的是整个数组的大小;常用在二维数组的传递中。

语法类型:数据类型(*指针名)[]。

image

 

指针数组:是一个元素都是指针的数组;常用于存储字符串数组;每个指针可以指向不同长度的数据。

语法类型:数据类型 *指针名[]。

image

 常量指针:指向常量的指针,指向内容是常量;内容不能修改,地址可以修改(可以通过修改地址间接修改内容);常用于函数参数,防止修改数据。

语法形式:const 数据类型 * 指针名;数据类型 const  * 指针名。

image

 

指针常量:指针本身是常量,指向不能改变;可以修改内容,地址无法修改;必须要在定义时初始化 。

语法:数据类型* const 指针名。

image

特殊类型:常量指针常量:const 类型名 * const 指针名;地址和内容都无法改变。

 

函数指针:指向函数的指针,通过调用该指针来使用该函数;常用于回调函数、函数表;可以指向匹配签名的任何函数。

语法类型:返回类型 (*函数名)(参数列表)。

image

指针函数:返回值是指针类型的函数。

语法类型:返回类型 *函数名 (参数列表)。

image

 

记忆技巧:

1.数组指针和指针数组 :()中有*指针名;是指针,指向数组;无(),指针名和[]结合,是数组,元素是指针。

2.常量指针和指针常量:const 在*左边,指向的值不变,是常量指针;const在*右边,指向的地址不变,是指针常量。tips:指针常量需初始化。

3.函数指针和指针函数:()中有*指针名;是指针,指向函数;无(),指针名和(参数列表)结合,是函数,返回值是指针。
总结:()中的优先级最高,若()中有*指针名,则是指针,后面的属性定义指向数组or函数;无()保护*指针名,则是一种具体的类型。

应用场景:

1.数组指针:二维数组作为函数参数,矩阵处理。

2.指针数组:字符串数组,命令行参数。

3.常量指针:函数参数保护,防止意外修改,只可读,不可修改。

4.指针常量:硬件寄存器地址访问,固定地址访问,可以修改内容。

5.函数指针:回调函数,函数表。

6.指针函数:工厂模式,动态内存分配。

注意事项:

1.数组指针和指针数组声明注意()的位置。

2.常量指针只是限制通过指针修改数据,但不限制修改指针变量。

3.指针函数不要返回局部变量的地址(栈内存会在函数返回后释放)。

4.函数指针需要和所指向函数的签名完全匹配。

示例程序:

#include<stdio.h>int add(int a, int b);
int sub(int a, int b);
int* funa(int* p);
int main()
{//数组指针:指向数组的指针        int(*ptr)[5]//指针数组:一个数组,元素都是指针 int *arr[5]//常量指针:指向常量的指针,指向内容是常量,内容无法修改,地址可以修改 const int *ptr//指针常量:指针本身是常量,指向不能改变,可以修改内容,地址无法修改 int *const ptr//函数指针:指向函数的指针,通过调用该指针来使用该函数,返回类型(*函数名)(参数列表)//指针函数:返回指针的函数,返回类型 *函数名 (参数列表)//1.数组指针:指向数组的指针        int(*ptr)[5]printf("数组指针\n");int arr[5] = { 1,2,3,4,5 }; int i;int(*ptr1)[5] = arr; //数组名就是数组地址 取地址方式1for (i = 0; i < 5; i++){printf("%d\n", (*ptr1)[i]);}int(*ptr2)[5] = &arr; //数组名就是数组地址 取地址方式2for (i = 0; i < 5; i++){printf("%d\n", (*ptr2)[i]);}printf("数组指针\n");//2.指针数组:一个数组,元素都是指针 int *brr[5]printf("指针数组\n");int a = 1, b = 2, c = 3;int *brr[3] = {&a,&b,&c};for (i = 0; i < 3; i++){printf("%d\n", *brr[i]);}for (i = 0; i < 3; i++){printf("%p\n", brr[i]);}printf("%p\n", &a);printf("%p\n", &b);printf("%p\n", &c);printf("指针数组\n");//3.常量指针:指向常量的指针,指向内容是常量,内容无法修改,地址可以修改 const int *ptr//可以通过修改地址来修改值int ab = 100;int bc = 200;const int ac = 10;const int *ptr3 = &ab; //指向ab,但通过指针无法修改ab的值printf("常量指针\n");printf("%d\n", *ptr3);printf("%p\n", ptr3);//*ptr3 = 30;ptr3 = ∾printf("%p\n", &ab);printf("%p\n", &ac);printf("%d\n", *ptr3);printf("%p\n", ptr3);ptr3 = &bc;printf("%d\n", *ptr3);printf("%p\n", ptr3);printf("常量指针\n");//4.指针常量:指针本身是常量,指向不能改变,可以修改内容,地址无法修改 int *const ptrint abc = 99, bac = 88, aaa=55, bbb=66;printf("指针常量\n");printf("%p\n", &bac);printf("%p\n", &abc);int* const ptr4 = &abc;*ptr4 = 77;printf("%p\n", ptr4);printf("%d\n", *ptr4);*ptr4 = aaa;printf("%p\n", ptr4);printf("%d\n", *ptr4);*ptr4 = bbb;printf("%p\n", ptr4);printf("%d\n", *ptr4);printf("指针常量\n");//ptr4 = &bac;//5.函数指针:指向函数的指针 返回类型(*func)(参数列表)printf("函数指针\n");int abcd = 0;int(*func)(int a, int b);func = NULL;printf("%p\n", add);printf("%p\n", func);func = &add;printf("%p\n", func);abcd = func(3, 4);printf("%d\n", abcd);printf("%p\n", func);printf("%p\n", sub);func = sub;printf("%p\n", sub);printf("%p\n", func);abcd = sub(9, 4);printf("%d\n", abcd);printf("函数指针\n");//6.指针函数:返回指针的函数,返回类型 *函数名 (参数列表)printf("指针函数\n");int aabb = 123;int *ptr5;int* ptr6= funa(&aabb);printf("%p\n", &aabb);printf("%p\n", funa);ptr5 = funa(&aabb);printf("%p\n", ptr5);printf("%p\n", ptr6);printf("%d\n", *ptr5);printf("%d\n", *ptr6);printf("指针函数\n");return 0;}int add(int a, int b)
{return a + b;
}
int sub(int a, int b)
{return a - b;
}int* funa(int *p)
{return p;
}

  

http://www.jsqmd.com/news/359219/

相关文章:

  • 2.8 cookie session
  • ESP32设备连接WiFi (STA站点模式)
  • 洛谷P1012
  • 线性规划的经典应用:从数学模型到企业决策实战
  • 洛谷P5435
  • 一键配置RK3588网络与SSH远程连接
  • 细胞多尺度仿真软件:PhysiCell_(2).PhysiCell软件介绍及安装
  • W11电脑无法获取到Windows服务器DHCP的IP地址,如何解决?
  • 新手入门指南:一文看懂环境搭建、模型配置与 WebUI 远程访问
  • ABC_444
  • 低代码处理物联网大数据:Node-RED进阶教程
  • 大数据领域 Hadoop 高可用方案的设计与实现
  • 细胞多尺度仿真软件:MCell_(14).并行计算与大规模仿真
  • 细胞多尺度仿真软件:MCell_(11).MCell在生物医学研究中的应用实例
  • php python+vue网上汽车销售系统的开发
  • 大数据可视化中的用户行为分析展示
  • 深入解析:【无线电控制与数据链探测系统】第2章 无线电与数据链基础
  • 细胞多尺度仿真软件:MCell_(10).仿真结果的分析与可视化
  • 从零开始用自定义 Triton 内核编写 FlashAttention-2
  • ApiScan
  • 神经网络模型基础与简单实现
  • Hadoop vs Spark:哪种大数据框架更适合物联网数据处理?
  • 线性代数资源合集(第二辑)
  • LOJ6485
  • 大数据领域数据清洗的实用工具推荐
  • 别再拍脑袋上线了:用大数据把 A/B 测试和在线实验平台这件事干“正经”
  • 口腔医学教程资源合集
  • php python+vue网上同学录系统_开题报告
  • 提示工程架构师必知:Agentic AI的3大设计模式
  • 基于springboot的运动服服装销售系统