复杂指针

C语言后记-24 C语言复杂指针阅读方法 - 右左法则 简化的方法就是typedef,这个是使用的非常广的,可以简化指针和数组的定义。3.遇到圆括号或方括号时可以确定部分类型,并调转方向。1.从最里边的圆括号中未定义的标识符看起。不过我还是用比较容易理解的方式记录一下。但是在简化之前应该先读懂这个代码!4.重复2 3 步骤,直到阅读结束。2.首先往右看,在往左看。可以看下我之前的文章。 阅读详情
右左法则----复杂指针解析

因为C语言所有复杂的指针声明,都是由各种声明嵌套构成的。如何解读复杂指针声明呢?右左法则是一个既著名又常用的方法。不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的,两者可以说是相反的。右左法则的英文原文是这样说的:

The right-left rule: Start reading the declaration from the innermost parentheses, go right, and then go left. When you

  encounter parentheses, the direction should be reversed. Once everything in the parentheses has been 

parsed, jump out of it. Continue till the whole declaration has been parsed.


这段英文的翻译如下:

右左法则:首先从最里面的圆括号看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。一旦解析完圆括号里面所有的东西,就跳出圆括号。重复这个过程直到整个声明解析完毕。

         笔者要对这个法则进行一个小小的修正,应该是从未定义的标识符开始阅读,而不是从括号读起,之所以是未定义的标识符,是因为一个声明里面可能有多个标识符,但未定义的标识符只会有一个。

         现在通过一些例子来讨论右左法则的应用,先从最简单的开始,逐步加深:

int (*func)(int *p);

首先找到那个未定义的标识符,就是func,它的外面有一对圆括号,而且左边是一个*号,这说明func是一个指针,然后跳出这个圆括号,先看右边,也是一个圆括号,这说明(*func)是一个函数,而func是一个指向这类函数的指针,就是一个函数指针,这类函数具有int*类型的形参,返回值类型是 int。

int (*func)(int *p, int (*f)(int*));

func被一对括号包含,且左边有一个*号,说明func是一个指针,跳出括号,右边也有个括号,那么func是一个指向函数的指针,这类函数具有int *和int (*)(int*)这样的形参,返回值为int类型。再来看一看func的形参int (*f)(int*),类似前面的解释,f也是一个函数指针,指向的函数具有int*类型的形参,返回值为int。

int (*func[5])(int *p);

func右边是一个[]运算符,说明func是一个具有5个元素的数组,func的左边有一个*,说明func的元素是指针,要注意这里的*不是修饰 func的,而是修饰func[5]的,原因是[]运算符优先级比*高,func先跟[]结合,因此*修饰的是func[5]。跳出这个括号,看右边,也是一对圆括号,说明func数组的元素是函数类型的指针,它所指向的函数具有int*类型的形参,返回值类型为int。


int (*(*func)[5])(int *p);

func被一个圆括号包含,左边又有一个*,那么func是一个指针,跳出括号,右边是一个[]运算符号,说明func是一个指向数组的指针,现在往左看,左边有一个*号,说明这个数组的元素是指针,再跳出括号,右边又有一个括号,说明这个数组的元素是指向函数的指针。总结一下,就是:func是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向具有int*形参,返回值为int类型的函数。

int (*(*func)(int *p))[5];

func是一个函数指针,这类函数具有int*类型的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组。

要注意有些复杂指针声明是非法的,例如:

int func(void) [5];

func是一个返回值为具有5个int元素的数组的函数。但C语言的函数返回值不能为数组,这是因为如果允许函数返回值为数组,那么接收这个数组的内容的东西,也必须是一个数组,但C语言的数组名是一个右值,它不能作为左值来接收另一个数组,因此函数返回值不能为数组。

int func[5](void);

func是一个具有5个元素的数组,这个数组的元素都是函数。这也是非法的,因为数组的元素除了类型必须一样外,每个元素所占用的内存空间也必须相同,显然函数是无法达到这个要求的,即使函数的类型一样,但函数所占用的空间通常是不相同的。

         作为练习,下面列几个复杂指针声明给读者自己来解析。

int (*(*func)[5][6])[7][8];

int (*(*(*func)(int *))[5])(int *);

int (*(*func[7][8][9])(int*))[5];

         实际当中,需要声明一个复杂指针时,如果把整个声明写成上面所示的形式,对程序可读性是一大损害。应该用typedef来对声明逐层分解,增强可读性,例如对于声明:

int (*(*func)(int *p))[5];

可以这样分解:

typedef  int (*PARA)[5];
typedef PARA (*func)(int *);

这样就容易看得多了。 
 

 

答案,同时给出用typedef的分解方法:


int (*(*func)[5][6])[7][8];

func是一个指向数组的指针,这类数组的元素是一个具有5X6个int元素的二维数组,而这个二维数组的元素又是一个二维数组。

typedef int (*PARA)[7][8];
typedef PARA (*func)[5][6];


int (*(*(*func)(int *))[5])(int *);

func是一个函数指针,这类函数的返回值是一个指向数组的指针,所指向数组的元素也是函数指针,指向的函数具有int*形参,返回值为int。

typedef int (*PARA1)(int*);
typedef PARA1 (*PARA2)[5];
typedef PARA2 (*func)(int*);

int (*(*func[7][8][9])(int*))[5];

func是一个数组,这个数组的元素是函数指针,这类函数具有int*的形参,返回值是指向数组的指针,所指向的数组的元素是具有5个int元素的数组。

typedef int (*PARA1)[5];
typedef PARA1 (*PARA2)(int*);
typedef PARA2 func[7][8][9];
C语言中的复杂指针 这里的type表示指针所指向的变量类型,表示指向的指针,它指向另一个指针,而这个指针最终指向一个数据类型为type的值。数组指针是一个指针,它指向整个数组,而不是指向数组中的单个元素。这里,type表示数组元素的类型,size表示数组的大小,表示指向数组的指针。这里,是函数的返回类型,是函数指针的名字,是函数参数的类型。在 C 语言中,指针不仅可以指向基本数据类型的变量,还可以指向指针、数组、函数等复杂结构。了解如何定义和使用这些复杂的指针是掌握 C 语言的重要步骤。指向指针的指针:用于操作二级指针。 阅读详情

相关推荐

C语言右左法则----复杂指针解析

C语言右左法则----复杂指针解析 因为C语言所有复杂的指针声明,都是由各种声明嵌套构成的。如何解读复杂指针声明呢?右左法则是一个既着名又常用的方法。不过,右左法   则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用

右左法则

右左法则     对于一些长或者复杂的声明的名称,理解起来有点困难。但是右左法则能很好的解决这个问题。     而右左法虽不是不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的。 这个法则的具体的应用:从内部括号开始阅读(必须从变量名开始)声明,向右看,然后向左看。当碰到一个括号的时候就调转阅读的方

程序猿养成记 734

Agent本地部署教程详细步骤

在开始之前,你需要明确你要部署的Agent是什么。如果你需要部署其他Agent,请参考其官方文档调整步骤。

weixin_39673931的博客 2502

[zz]复杂指针解析

因为C语言所有复杂的指针声明,都是由各种声明嵌套构成的。如何解读复杂指针声明呢?右左法则是一个既著名又常用的方法。不过,右左法则其实并不是C标准里面的内容,它是从C标准的声明规定中归纳出来的方法。C标准的声明规则,是用来解决如何创建声明的,而右左法则是用来解决如何辩识一个声明的,两者可以说是相反的。右左法则的英文原文是这样说的:The right-left rule: Start rea...

weixin_30401605的博客 265

内存优化--LOGBACK导致内存告警

一.故事背景 由于开辟新市场需要,开发了新的项部署在海外平台,其中最消耗内存的功能是消费kafka消息(最开始预计一天有1千万的量),部署完之后运行一段时间发现出现内存告警问题。 二.分析问题 出现内存告警,(新项目是低配置机器 2C4G * 2台)第一个念头是去查看堆空间设置的情况,看到jvm启动命令中堆空间都是直接指定大小,说明问题不是出在堆空间 -Xmx3g -Xms3g 先不管这些,去查看总的内存使用情况,发现总的内存空间使用将近有92% = 3.68G,那么这多出来使用的0.6

qq_33199919的博客 6052

【第1章】基于FPGA的图像形态学处理学习教程——目录

本课程介绍图像形态学处理技术,通过腐蚀、膨胀、开运算、闭运算等算子对图像进行优化。腐蚀可去除边缘杂色使线条更清晰,膨胀能填补缺口修复图像,开运算擅长去噪,闭运算则用于修补断裂。课程内容涵盖四大形态学处理的理论分析、MATLAB仿真和FPGA开发实现,包括腐蚀、膨胀、开闭运算以及顶帽变换等操作,最后探讨形态学处理的实际应用场景。通过仿真测试和FPGA开发实践,帮助学员掌握图像"美容塑型"的核心技术。

MATLAB,verilog,python,opencv,tensorflow,caffe,C,C++ 338

指针的右左法则

1.首先从最里面的圆括号开始阅读 2.首先向右看,再往左看 3.每当遇到圆括号或者方括号时可以确定部分类型,并调转阅读方向 4.重复2,3的步骤直到阅读结束

m0_74234485的博客 1217

目前固态激光雷达在机器人领域的应用难点汇总

固态激光雷达在机器人领域面临性能与成本的双重挑战:探测性能上,动态范围不足(60-80dB)导致高/低反射物体识别困难,近距盲区(30-50cm)与长距精度(±3cm)矛盾突出;结构上视场角与点云密度难以平衡,多雷达拼接又带来同步误差。成本方面,核心元件(SPAD/OPA芯片)良率低(<50%)、校准工序复杂,单机成本超200美元。环境适应性上,粉尘附着、振动偏移(±2°)和光衰(1万小时衰减15%)制约可靠性。

start_up_go的博客 481

C语言的右左法则

右左法则:首先从最里面的圆括号看起,然后往右看,再往左看。每当遇到圆括号时,就应该掉转阅读方向。/*funcparr是函数指针数组*///函数名就是函数的首地址,所以&func1和func1都可以,两种写法/*funcparrp是函数指针数组指针*//*funcparrpp是函数指针数组指针的指针*/return 0;

qq_45964785的博客 718

STM32实现简单的智能电子相框

具体的代码案例和详细的代码实现超过5000字,无法在此篇文章中提供。但是,你可以参考STM32的官方文档和相应的图形库和多媒体库的文档,以获得更详细的实现细节和代码示例。对于硬件,我们可以选择使用STM32开发板,如STM32F4 Discovery。对于软件开发环境,我们将使用Keil MDK-ARM作为开发工具,并使用STM32CubeMX进行代码配置。在本文中,我们将使用STM32单片机实现一个简单的智能电子相框,包括显示照片、播放视频和音乐功能。接下来,我们将详细描述实现智能电子相框的步骤。

2401_85625565的博客 1006

多无人车协同探索开源包部署教程及常见报错解决方式

本博客将介绍项目的基本概念、部署步骤以及常见问题的解决方案。该项目利用 RRT(Rapidly-exploring Random Tree)算法,通过多机器人协作进行高效的环境探索,适用于自动化与自主导航任务。项目简介:介绍该项目的核心算法、特点及应用场景,展示如何通过多个机器人共同工作来提升探索效率。部署教程:详细讲解如何在 ROS Noetic 环境中部署该项目,安装依赖、创建工作空间、克隆代码并编译项目。项目运行:包括单机器人与多机器人自主探索的示例,帮助读者快速理解和实践项目。

慕羽★的博客 1764

复杂指针解析

复杂指针解析-----右左法则(用于理解复杂指针的声明) 右左法则----首先从最里面的圆括号看起,然后往右看,再往左看每当遇到圆括号时,就应该调转阅读方向,一旦解析完圆括号里面的所有内容,就跳出圆括号,重复这个过程,直至整个声明解析完毕。 应该从未定义的标识符开始阅读,而不是从括号阅读起,之所以是未定义的标识符,是因为一个声明里面可能有多个标识符,单未定义的标识符只会有一个。 先热热身~ ...

请叫我皮皮虾的博客 538

Codex 接入国产大模型完整指南:CC-Switch 与 Codex++ 的工程化选型

Codex 默认走 OpenAI Responses API,而 DeepSeek、GLM、Kimi 等国产模型只提供 OpenAI-compatible 的 Chat Completions——两套协议在消息结构、流式响应、reasoning 字段、tool call 上都不兼容,所以"改个 Base URL + 填国产 Key"这种朴素操作根本跑不通。本文从架构师视角出发,把 Codex 接入国产大模型这件事讲透:先剖析协议链路到底卡在哪,再对比 CC-Switch和 Codex++两套主流方案的差异

少说,多做 3855

指针扫盲--复杂指针解析

其实也就笔试的时候遇到过让解释复杂指针,平时到也没太这样用过; 在网上搜了一些资料,大体解释都相同,应该都是出自一个人或者一本书一手吧; 我身边广为流传是megaboy同学的指针扫盲,学习; 记录下,基本例子是摘自指针扫盲第八章附加自己的理解; 指针是c的核心,希望自己以后能有自己的见解...   首先介绍一个概念,[左右法则].. 右左法则:首先从最里面的圆括号看起,然后往右看,再

罗马非一日建成 535

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

四、复杂指针解析

C语言复杂指针的理解,是能够深入阅读和使用C语言的关键

kingsdai的博客 754

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

C语言之指针-复杂指针类型解析

1.什么是复杂指针 int a; int *a; int * (*(*a)); int *(*(*pfun)(int *))[5];(1)指向指针的指针 通常我们称int *a,指针a就是一个常见的指向int类型的指针变量。int **a就是一个二级指针,它是一个指向指针的指针,int *是一个整体,被指向对象。 而三级指针int ***a同样如此, 所指的对象是一个int **类型,所...

qq_37291326的博客 986

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

复杂指针的定义(含复杂函数指针)

引言 指针是C/C++语言中很重要的机制,一些C语言高级用法基本都需要指针的参与。本文从定义的角度, 解析各类用到指针的定义。 具体解析过程              int   p; 定义普通变量p int   *p; 定义一个指向int变量的指针p int   p[3]; 定义一个含有三个元素的数组p int   *p[3]; []优先级比*高,因此p先与[]结合

CHENXIAO的专栏 4184

复杂的指针

要理解指针, 尤其是和一些其他类型修饰符放在一起的指针, 看上去很难,其实不然。一个类型声明里会出现很多修饰符,他们就像普通的表达式一样,有优先级和结合性。只要掌握了这些规律,分析一个复杂的指针类型就很容易了。 分析时, 先从变量名开始,然后根据修饰符的优先级结合性,一步一步分析。下面看几个最常用的例子: int p;  // 普通的int变量 int *p;

David的专栏 1775

复杂指针的声明和关于指针的几个小例子

参考自:《C和C++程序员面试秘籍》 a: 一个有10个指针的数组,该指针是指向一个整型数的 int *a[10] b:一个指向有10个整型数数组的指针 int (*a)[10] c:一个指向函数的指针,该函数有一个整形参数并返回一个整型数 int (*fun)(int) d:一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数 int (*fun[10])(int) 如何解读复杂指针? int (*func)(int *p); 解析上面这行代码: 首先找到未定义的标识

u012127512的博客 333

【C语言指针】分析C语言复杂指针

前言 指针是一种保存变量地址的变量,简单指针容易分析,但是当指针稍微复杂,就很容易无从下手,比如: char *(*(**foo[][8])())[]; 下面将会由浅入深的探究指针 普通指针 #include <cstdio> #include <iostream> using namespace std; int main() { int a = 1; int * pa = &a; int ** ppa = &pa; prin

郭同学如是说 1422

复杂指针的声明

复杂指针的声明 用变量a给出下面的定义:  定义一个整型数。定义一个指向整型数的指针。定义一个指向指针的指针,它指向的指针是一个指向整型数指针。定义一个有10个整型数的数组。定义一个有10个指针的数组,该指针是指向一个整型数的指针。定义一个指向有10个整型数数组的指针。定义一个指向函数的指针,该函数有一个整型参数并返回一个整型数。定义一个有10个指针的数组,该指针指向一个函数,该函数有一个

逍遥小章 564

复杂指针几例

未完,待续... 786
上一篇: 自定义hadoop map/reduce输入文件切割InputFormat 更改输入value的分隔符
下一篇: linux进程优先级、进程nice值(转载)
codestinity
博客等级 码龄16年 29粉丝 7原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值