C++ 变量判定的螺旋法则


C++ 中一个标识符配合着各种修饰界定符,使得标识符的本意不那么直观一眼就能看出,甚至需要仔细分析,才能知道该标识符的具体你含义。

比如:

void (*signal(int, void (*fp)(int)))(int);

其中 signal 是什么?

螺旋法则

对于如何进行变量的辩识,有个非官方的 “顺时针/螺旋法则(Clockwise/Spiral Rule)” 可用来帮助辩识。

该法则的内容,简单来说,为了搞清楚一个未知标识符的含义,我们可以:

  1. 从我们需要判定的标识符开始,顺时针画圈,遇到如下符号时,用对应的语义替换:
  • [x][] => 容量为 x 的数组或数组
  • (type1,type2...) => 接收 type1type2... 的函数,返回值为(待定)
  • * => 指向(类型待定)的指针
  1. 重复上面的步骤直到语句中所有符号都被遍历过。
  2. 始终优先解析括号括起来的部分。

实地演练

一个简单的示例

先从一个简单的开始,判定如下语句中 str 的含义:

                     +-------+
                     | +-+   |
                     | ^ |   |
                char *str[10];
                 ^   ^   |   |
                 |   +---+   |
                 +-----------+

根据螺旋法则,如上面线图标识所示,

  • str 这个需要被判定的对象出发。
  • 螺旋路径上第一次遇到的是 [ 左方括号,由此我们知道,str 是一个尺寸为 10 的数组。
  • 继续旋转,遇到 *,所以 str 是一个尺寸为 10 的数组,数组元素为指针。
  • 继续,遇到 ; 标识语句的结束。
  • 再继续,遇到 char,所以 str 是一个尺寸为 10 的数组,数组元素为指向 char 类型的指针。

进阶

回到文章开头那个语句,来判定其中 signal 的含义。

                      +-----------------------------+
                      |                  +---+      |
                      |  +---+           |+-+|      |
                      |  ^   |           |^ ||      |
                void (*signal(int, void (*fp)(int)))(int);
                 ^    ^      |      ^    ^  ||      |
                 |    +------+      |    +--+|      |
                 |                  +--------+      |
                 +----------------------------------+

由螺旋法则画出如上的线图,进而可分析:

  • 从要判定的 signal 出发首次遇到 ( 左括号,表示 signal 是一个函数,入参为 int 和 ...
  • 此处需要需要进一步运用螺旋法则先确定 fp 的含义,才能进而确认 signal 这个函数的完整入参。所以从 fp 了发进行一次子螺旋。
  • 因为需要优先解析括号括起来的部分,所以转一圈回来首次遇到的是 *,由此 fp 是一个指针。
  • 继续解析 fp,遇到 (,所以 fp 是一个指向函数的指针,这个函数接收一个 int 类型的入参。
  • 继续下去,遇到 void,所以 fp 是一个指向函数的指针,这个函数接收一个 int 类型的入参并且返回值为空。
  • 至此完成了 fp 的解析,可以知道 signal 的类型为:
    • 是一个函数,入参为:

      • 一个 int 类型
      • 一个指向函数的指针,这个函数接收一个 int 类型的入参并且返回值为空
  • 路径跑到 signal 的螺旋中,遇到 *(紧邻 signal 左边),所以 signal
    • 一个函数,入参为:

      • 一个 int 类型
      • 一个指向函数的指针,这个函数接收一个 int 类型的入参并且返回值为空
    • 返回值为指针
  • 再继续,遇到 (,接上面,返回值为指向另一函数的指针,被指向的这个函数接收一个 int 入参。
  • 最后,遇到 voidsignal 返回值指向的这个函数的返回值为空。

最后捋一下 signal 的完整类型为:接收一个 int,一个指向接收一个 int 并且返回值为空的函数的指针,这两个参数的函数,并且返回值为指向一个接收 int 型返回为空的函数...Orz。

成员函数的判定

螺旋施法没有给出在 const 参与的情况下的判定,不过因为 const 默认修饰紧邻其左边的元素,如果右边无元素,则修饰左边的元素。因此只需要将 const 和它修饰的元素作为整体来看,就还是可以使用螺旋法则的。

考察如下语句:

const int*const Method3(const int*const&) const;

当函数后面紧跟一个 const 时,表示该成员函数的作用域内 *this 是常量,即无法在该函数体内对所类的实体进行修改。

下面对上面的语句进行分析:

  • Method3 出发,遇到 (,所以 Method3 是一个函数,接收一个引用作为入参 const int*const& 部分。
  • 该引用的类型是 const int*const,指向整形常量的常量指针。
  • 继续遇到 *const,所以函数的返回值为常量指针。指针指向的类型为 const int 整形常量。
  • 函数末尾的 const 如前所述,标识函数体内不修改实例。

相关资源

原文地址:https://www.cnblogs.com/Wayou/p/cpp_clockwise_spiral_rule.html

时间: 2024-11-13 08:40:16

C++ 变量判定的螺旋法则的相关文章

[F2016061803] ES6的模块导入与变量解构的注意事项

在ES6中变量解构是这样的: const a = { b: 1 } const { b } = a 我们可以直接用解构赋值来获得对象的同名属性,这等效于: const b = a.b 除了变量的解构赋值,ES6的模块导入也提供了相似的语法: import { resolve } from 'path' 如果使用webpack构建项目的话,注意这里的解构与普通变量的解构是有所区别的,比如在a.js里有以下代码: export default { b: 1 } 如果按照普通变量的解构法则来导入这个包

Python学习之变量的作用域

学习地址:http://www.jianshu.com/p/17a9d8584530 1.变量作用域LEGB 1.1变量的作用域 在Python程序中创建.改变.查找变量名时,都是在一个保存变量名的空间中进行,我们称之为命名空间,也被称之为作用域.python的作用域是静态的,在源代码中变量名被赋值的位置决定了该变量能被访问的范围.即Python变量的作用域由变量所在源代码中的位置决定. 1.2高级语言对数据类型的使用过程 一般的高级语言在使用变量时,都会有下面4个过程.当然在不同的语言中也会有

static extern const修饰符

const const修饰的东西不能被修改(由左至右解读-->顺时针螺旋法则) 指针类型根据位置的不同可以理解成3种情况: 1.常量指针 NSString * const pt1; //常量指针,指向一个字符串 //pt1初始化之后不能赋值,指向的对象值可以修改. //定义字符串常量 //NSString* const [email protected]"123"; @"123"存储在文字常量区,相同的字符串只存储一份 NSString* [email pro

2017-9-11 - A - webServer

1 * /index.html * /reg?username=fancq&password=123456&nickname= * 在GET请求中,URI可能会有上面两种情况. * HTTP协议中规定,GET请求中的URI可以传递参数,而规则时请求的资源后面以 * "?"分割,之后则为所有要传递的参数,每个参数由: * name=value的格式保存,每个参数之间使用"&"分割. * 这里的处理要求: * 将"?"之前的内

《编程珠玑》

第1章 开篇 问题: 输入: 一个最多包含n个正整数的文件,每个数都小于n,其中n=107.如果在输入文件中有任何整数重复出现就是致命错误.没有其它数据与该整数相关联. 输出: 按升序排列的输入整数的列表. 约束: 最多有(大约)1MB的内存空间可用,有充足的磁盘存储空间可用.运行时间最多几分钟,运行时间10秒就不需要进一步优化了. 解决方案: 位向量     //phase 1:initialize set to empty         for i = [0,n)            

bash的基本特性

Bash基本特性: 首先得从逻辑运算来说起: 与运算  && 两个判断条件都必须为真时,状态才为真,否则都为假,在此1是真,0是假 1 && 1 = 1 1 && 0 = 0 0 && 1 = 0 0 && 0 = 0 或运算 || 两个判断条件中都必须为假时,那么这个或运算就为假 0 || 0 = 0 0 || 1 = 1 1 || 0 = 1 1 || 1 = 1 非运算 ! !1=0 //这里的意思就是,不是真,那就是假

week4

JavaScript 1.是什么:基于浏览器 基于(面向)对象 事件驱动 脚本语言 2.作用:表单验证,减轻服务器压力 添加野面动画效果 动态更改页面内容 Ajax网络请求 () 3.组成部分:ECMAScript() DOM(文档对象模型document) BOM(浏览器对 象模型) ECMAScript:语法 变量和数据类型 运算符 逻辑控制语句 关键 字.保留字 对象 4.基本结构:<script type="text/javascript"> 语句 </scr

Linux中bash中的几种基础特性汇总!

首先需要知道什么是shell?如果将Linux内核当作一个地球的核心,那么shell就是地壳.shell本身也是一个应用程序,为我们提供了使用系统的接口.shell程序有很多种,目前主流发行版大多数默认使用bash,其次还有sh,tcsh,csh,fish等,其程序存储在/etc/shells目录下. 由于目前最常用的bash,所以就以bash为例来说一说bash的基础特性,偷偷说一句,其实我也是个新手,其他的shell并未接触,不敢轻易去说,当然本文中难免有错误,还请各位不吝赐教,让大家共同进

OPEN CASCADE Multiple Variable Function

OPEN CASCADE Multiple Variable Function [email protected] Abstract. Multiple variable function with gradient and Hessian matrix is very very import in OPEN CASCADE optimization algorithms. In order to understand these optimization algorithm better, l