IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言的优先性与结合性——Think like a computer -> 正文阅读

[C++知识库]C语言的优先性与结合性——Think like a computer

前言

写这篇就为了再遇到稍微复杂一点的表达式不至于绕晕;优先级和结合方向不再赘述,随便一搜就都有了,在优先级和结合方向上我借鉴的是这篇
注意,虽然有优先级和结合方向一说,但是程序不止是给机器编译的,也是给人看的,做个人,该括括号的时候,尽量提高可读性吧!
如有错误欢迎评论指出。

故事的开端

	for (i = 0; i < XSK_RING_PROD__DEFAULT_NUM_DESCS; i ++)
		*xsk_ring_prod__fill_addr(&xsk_info->umem->fq, idx++) =
			xsk_alloc_umem_frame(xsk_info);

第一眼看过去,你知道执行顺序吗?嗯……第一眼觉得很简单,然后有一点犹豫,因为不知道为什么会这样执行,只是觉得就该这样。
然后就有了这篇文章,不止自己要清楚,还要给别人讲清楚。

什么是运算符的优先级和结合方向

优先级

先拿简单例子来讲:

*p++;

我们知道自增运算符++的优先级与取值运算符*相同,恰好是同优先级的特例,同优先级看结合方向(同优先级结合方向是一致的),那么把自己想象成计算机,看向这条语句,我们只解析,不纠错:

注:随便抄的一个例子,里面说自增符++的优先级高于取值符* 仔细一看发现说的错的,优先级根本是一样的,只好先说同优先级的例子;

Think like a computer:
> 我们从高优先级开始扫描,其他部分统一视作一个"块",发现优先级2:
> [*] [块0] [++]
> 按结合方向处理,2优先级的从右往左,也就是先处理右边的[++]
> [++]单目运算符,直接往左;
> 从[++]往左,到[块0],再撞到运算符[*],好了停下来,我们结合一下:
> [*]([块0]++),恰巧[块0]里面没有关键字符要处理了,直接:
> [*](p++)
> 到这里人已经一眼可以看出来结果了,可是计算机要再处理一下:
> 处理下一个优先级2的运算符,括号外往左,到[*],右结合,向右看,只有一整个块(p++),所以:
> (*(p++)),整个语句已成块,工作结束;

补一张图示:
在这里插入图片描述

所以上面那个例子应该等效为:

*(p++);

从可读性上来讲,还是后者更好一些;

结合方向

从右往左意味着:

  • 同优先级下处理顺序从右往左(见上个例子);
  • 双目运算符先向右处理;
  • 单目运算符直接往有效方向处理,无效方向括号封住;(如上个例子,但按照语言的设计,就算先向右处理应该也无伤大雅)

还是先简单例子:

a=b=c

赋值运算符=是从右往左,也就是先右后左;

Think like a computer:
> 我们从高优先级开始扫描,其他部分统一视作一个"块",发现优先级14:
> [块0] [=]① [块1] [=]② [块2]
> 按结合方向处理,14优先级的从右往左,也就是先处理右边的[=]②
> [=]②双目运算符,先看向右,右边的[块2],再撞到尽头,结束,画上右括号标记一下,恰好没有关键字符要处理了,偷个懒直接处理成c
> [块0] [=]① [块1] [=]② c)
> 再从[=]②向左,到[块1](顺便处理成b),再撞到运算符[=]①,好了停下来,我们画上左括号标记结合:
> [块0] [=]①(b = c)
>偷个懒,用箭头和括号代替接下来的文字描述:
> [=]① --> (b = c) --> 尽头
[块0] [=]①(b = c))
> 尽头 <-- [块0] <-- [=]①
([块0] [=]①(b = c))
> END

再来练一个例子,再次偷懒,还是画图快:

f1() * f2() + f3();

在这里插入图片描述

故事在这能结束吗?

回到一开始的例子:

*xsk_ring_prod__fill_addr(&xsk_info->umem->fq, idx++) =
			xsk_alloc_umem_frame(xsk_info);

简化一下:

*fill(&fq, idx++) = alloc_frame(info);

开始分析:
在这里插入图片描述
也就是说:

  1. 先从左到右把两个函数调用;
  2. 再对fill返回的地址进行取值;
  3. 再把alloc_frame函数返回的值赋给fill返回地址的取值。

和GDB跟的结果一样,那故事就在这结束吧。

总结

Think like a computer:

  1. 先处理高优先级运算符,同优先级按结合方向处理;
  2. 按照结合方向,从运算符延伸,撞到其他运算符或语句尽头即停止,画上分割括号;
  3. 括号运算符/分割括号内看做一个整体,单独讨论;

这种方法仅起一个帮助作用,能够让初学者遇到复杂式子时有一个范式,能够理解复杂语句执行的顺序。但真要快速理解复杂的代码,还得靠多年的经验和实际的调试。

吐槽

这段代码加个括号瞬间就没什么事情了:

	for (i = 0; i < XSK_RING_PROD__DEFAULT_NUM_DESCS; i ++)
		*(xsk_ring_prod__fill_addr(&xsk_info->umem->fq, idx++)) =
			xsk_alloc_umem_frame(xsk_info);
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-13 09:05:31  更:2021-09-13 09:06:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:24:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码