带你走进Cflow (三)·控制符号类型分析

news2024/11/25 4:56:39

目录

​编辑

1、控制符号类型

1.1  语法类

1.2  符号别名

1.3  GCC 初始化


1、控制符号类型

        有人也许注意到了输出中奇怪的现象:函数_exit 丢失了,虽然它在源文件中被printdir 调用了两次。这是因为默认情况下 cflow 忽略所有的一下划线开头的符号。为了将这样的符号包含进来,我们使用-i _ (or --include _)命令行选项。继续我们的例子:

$ cflow --number -i _ d.c
 1 main() <int main (int argc,char **argv) at d.c:85>:
 2 fprintf()
 3 atoi()
 4 printdir() <void printdir (int level,char *name) at d.c:42> (R):
 5 getcwd()
 6 perror()
 7 _exit()
 8 chdir()
 9 opendir()
 10 readdir()
 11 printf()
 12 ignorent() <int ignorent (char *name) at d.c:28>:
 13 strcmp()
 14 isdir() <int isdir (char *name) at d.c:12>:
 15 stat()
 16 perror()
 17 S_ISDIR()
 18 putchar()
 19 printdir()
 <void printdir (int level,char *name) at d.c:42>
 (recursive: see 4)
 20 closedir()

        通常情况下,参数--include 制定了一个符号类列表。默认的选项行为是输出中包含被请求的类。如果参数是以减号或插入符号开始的,则处理方式正好相反,是在输出结果中排除这种符号类。

        符号类‘_’包含了所有已下划线开头的符号。另一个有用的符号类是’s’,它表示静态函数或数据。默认情况下,静态函数是被包含在输出中的。为了省略他们,可以使用所给的-i ^s (or -i -s)选项。我们的样例程序 d.c 中定义了静态函数 isdir,运行 cflow -i ^s,可以在结果图中完全忽略这个函数和它的调用者。

$ cflow --number -i ^s d.c
 1 main() <int main (int argc,char **argv) at d.c:85>:
 2 fprintf()
 3 atoi()
 4 printdir() <void printdir (int level,char *name) at d.c:42> (R):
 5 getcwd()
 6 perror()
 7 chdir()
 8 opendir()
 9 readdir()
 10 printf()
 11 ignorent() <int ignorent (char *name) at d.c:28>:
 12 strcmp()
 13 putchar()
 14 printdir()
 <void printdir (int level,char *name) at d.c:42>
 (recursive: see 4)
 15 closedir()

        实际上,非包含符号(‘^’ 或 ‘-’)可以在-i 的参数中的任何地方使用,不仅限于开始。因此,选项-i _^s 表示包含除了静态函数以外的以下划线开头的符号。-i 选项可以累积使用,所以这个例子可以写为-i _ -i ^s。

        一个很重要的一点是,默认情况下 cflo 图中只包含函数。然而你可以使用符号类“x”来将变量输出。这个类包含所有的数据符号,包括全局变量和静态变量。如下例:

$ cflow --number -i x d.c
 1 main() <int main (int argc,char **argv) at d.c:85>:
 2 fprintf()
 3 stderr
 4 max_level <int max_level at d.c:37>
 5 atoi()
 6 printdir() <void printdir (int level,char *name) at d.c:42> (R):
 7 DIR
 8 dir
 9 getcwd()
 10 perror()
 11 chdir()
 12 opendir()
 13 readdir()
 14 printf()
 15 ignorent() <int ignorent (char *name) at d.c:28>:
 16 ignored_names <char *ignored_names[] at d.c:24>
 17 strcmp()
 18 isdir() <int isdir (char *name) at d.c:12>:
 19 stat()
 20 perror()
 21 S_ISDIR()
 22 NULL
 23 max_level <int max_level at d.c:37>
 24 putchar()
 25 printdir()
 <void printdir (int level,char *name) at d.c:42>
 (recursive: see 6)
 26 closedir()

        现在,第 3、4、16、23 行显示了数据标号,同时显示了可用的定义。然而请注意第 7、8 行。为什么类型名 DIR 和自动变量 dir 也被作为数据列出?为了回答这个问题,我们首先描述一线 cflow 对符号的概念定义。程序维持着符号表,使用 C 语言预处理关键字初始化。当解析输入文件时,cflow 更新了这些表。特别的,当遇到一个 typedef 时,它就将这个定义符号注册为数据类型。现在,DIR 在 d.c 中没有声明,所以 cflow 无法知道这是一个数据类型。所以他认为这是一个变量,这样一来输入:DIR *dir;就被解析为一个表达式,意思是“DIR乘以 dir”。

        当然这是错误的。有两种方式可以帮助 cflow 排除这种混淆。要么详细的声明 DIR为一个数据类型,要么让 cflow 运行预处理器,这样一来 cflow 就能看到头文件的内容,并自己做出决定。运行预处理器在下一章中。这一章我们主要集中精力在第一种方法。

        命令行选项--symbol (-s)声明这个符号的语法类。这个参数包含了被冒号隔开的两个字符串:--symbol sym:class。

        第一个字符串,sym 是 C 语言的符号表的识别码。第二个字符串,class,指定了与这个符号结合的类。特别的如果 class 是‘type’,那么符号 sym 就被记录为 C 语言类型定义。因此,修改上面的输出,运行:

$ cflow --number -i x --symbol DIR:type d.c

        另一个重要的符号类型是参数包装,这是宏的一种,经常用于兼容 ANSI 之前的编 译 器 来 保 护 函 数 原 型 中 的 参 数 声 明 的 源 。 比 如 下 面 的 声 明 , 从/usr/include/resolv.h 中获得,其中__P 是参数包装:

void res_npquery __P((const res_state, const u_char *, int, FILE *));

        为了能让 cflow 处理这样的声明,声明__P 为一个包装,例如:

cflow --symbol __P:wrapper *.c

        在所有的必须使用--symbol 选项的例子中,都是 cflow 不能识别给定的符号的意义,这要么是因为 cflow 不能看到类型的定义,就像‘DIR’的例子;要么是因为宏定义没有展开。这两种情况都可以用下一章藐视的预处理模式来解决。虽然有了预处理模式,但--symbol 选项还是有用的,我们会在下面的一节中看到:

1.1  语法类

总的来说,符号定义的语法类在 C 语言代码中是可以合法存在的。有如下的类:

关键字;关键字,比如‘if’、‘when’等

修改器;类型修改器,比如这个符号在数据类型后出现,可以修改数据的意义,比如指针‘*’。

修饰符;声明修饰符。能在 C 数据类型的前面和后面声明。你也许会经常声明gcc 关键字‘__extension__’作为修饰符:--symbol __extension__:qualifier

识别码;C 语言识别码。

类型;C 语言数据类型,比如‘char’,’int’。

包装器;他有两个用途,第一个是当没有运行预处理的时候声明一个参数包装器。这种用法在前面已经声明了。第二种,他表示任何能出现在声明符前或作为结尾的分号之前和后面可以跟一个括号表达式列表中的任何符号。

我们建议这样对 gcc 使用这个类:‘__attribute__’。

1.2  符号别名

        另一个--symbol 选项的用法是定义符号别名。别名是一个与被它引用的符号完全一样的标识。别名可以这样声明:--symbol newsym:=oldsym这样一来,符号 newsym 就被声明为和 oldsym 完全一样的类型了。

        符号别名也能在其他例子中作为定义符号类使用。对一些特殊的关键字是非常有用的,例如‘__restrict’: --symbol __restrict:=restrict。

1.3  GCC 初始化

下面的引用集是使用 gcc 时 cflow 的初始化选项。我们建议将他们放到 cflow.rc文件中:

--symbol __inline:=inline
 --symbol __inline__:=inline
 --symbol __const__:=const
 --symbol __const:=const
 --symbol __restrict:=restrict
 --symbol __extension__:qualifier
 --symbol __attribute__:wrapper
 --symbol __asm__:wrapper
 --symbol __nonnull:wrapper
 --symbol __wur:wrapper

带你走进Cflow (一)-CSDN博客

带你走进Cflow (二)·输出格式和递归调用-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1194561.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

离线视频ocr识别

sudo apt-get install libleptonica-dev libtesseract-dev sudo apt-get install tesseract-ocr-chi-sim python -m pip install video-ocrwindows安装方法&#xff1a; 下载安装 https://digi.bib.uni-mannheim.de/tesseract/tesseract-ocr-w64-setup-5.3.3.20231005.exe 下…

python自动化测试selenium核心技术3种等待方式详解

这篇文章主要为大家介绍了python自动化测试selenium的核心技术三种等待方式示例详解&#xff0c;有需要的朋友可以借鉴参考下&#xff0c;希望能够有所帮助&#xff0c;祝大家多多进步早日升职加薪 UI自动化测试过程中&#xff0c;可能会出现因测试环境不稳定、网络慢等情况&a…

JavaEE初阶学习:JVM(八股文)

1.JVM 中的内存区域划分 JVM 其实是一个Java进程~ java 进程会从操作系统这里申请一大块内存区域,给java代码使用~ 内存区域进一步划分,给出不同的用途 1.堆 new 出来的对象 (成员变量) 2.栈 维护方法之间的调用关系 (局部变量) 3.方法区(旧) / 元数据区 (新) 放的是类加载之…

K8S容器持续Terminating无法正常关闭(sider-car容器异常,微服务容器正常)

问题 K8S上出现大量持续terminating的Pod&#xff0c;无法通过常规命令删除。需要编写脚本批量强制删除持续temminating的Pod&#xff1a;contribution-xxxxxxx。 解决 获取terminating状态的pod名称的命令&#xff1a; # 获取media命名空间下&#xff0c;名称带contributi…

【论文解读】针对生成任务的多模态图学习

一、简要介绍 多模态学习结合了多种数据模式&#xff0c;拓宽了模型可以利用的数据的类型和复杂性&#xff1a;例如&#xff0c;从纯文本到图像映射对。大多数多模态学习算法专注于建模来自两种模式的简单的一对一数据对&#xff0c;如图像-标题对&#xff0c;或音频文本对。然…

Ubuntu系统使用apt-get管理软件工具

记录一下使用Ubuntu系统的apt-get管理软件工具 先查看一下系统的版本&#xff0c;可以看到这里使用的是Ubuntu20.04版本&#xff0c;版本代号focal rootmyw:~# uname -a Linux myw 5.4.0-70-generic #78-Ubuntu SMP Fri Mar 19 13:29:52 UTC 2021 x86_64 x86_64 x86_64 GNU/L…

NI USRP软件无线设备的特点

NI USRP软件无线设备 NI的USRP(Universal Software Radio Peripheral)设备是RF应用中使用的软件无线(SDR)。NI的USRP收发器可以在多个频段发送和接收RF信号&#xff0c;因此可用于通信工程教育和研究。通过与LabVIEW开发环境相结合&#xff0c;USRP可以实现使用无线信号验证无…

在gitlab中的使用kaniko打造流水线

文章目录 kaniko工具介绍环境说明系统版本组件版本组件部署参考链接 部署harbor下载解压、创建相关目录配置部署 gitlab集成harbor集成项目ci配置最终结果 kaniko工具介绍 kaniko 是一种从容器或 Kubernetes 集群内的 Dockerfile 构建容器镜像的工具。 kaniko 解决了使用 Doc…

云效流水线docker部署 :node.js镜像部署VUE项目

文章目录 引言I 流水线配置1.1 项目dockerfile1.2 Node.js 镜像构建1.3 docker 部署引言 云效流水线配置实现docker 部署微服务项目:https://blog.csdn.net/z929118967/article/details/133687120?spm=1001.2014.3001.5501 配置dockerfile-> 镜像构建->docker部署。 …

GEE:将鼠标变成十字指针,点击获取影像值,显示值到UI中

作者:CSDN @ _养乐多_ 本文记录了在 Google Earth Engine(GEE)开发中,将鼠标变成十字指针,点击获取影像值,显示值到UI中的代码片段。这段代码复制过去修改变量名就可以用了。 效果如下图所示, 文章目录 一、代码片段一、代码片段 使用的时候将 YLDImage 变量换成你屏…

C++结构体定义 创建 赋值 结构体数组 结构体指针 结构体嵌套结构体

结构体是什么&#xff1f; struct是自定义数据类型&#xff0c;是一些类型集合组成的一个类型。结构体的定义方式 #include<iostream> using namespace std;struct Student {string name;int age;int score; };创建结构体变量并赋值 方式一&#xff0c;先创建结构体变…

汽车标定技术(九)--标定常量与#pragma的趣事

目录 1. 不添加#pragma语句 2. 添加#pragma语句 3. 标定量只给flash空间&#xff0c;不给ram指定空间 4. 总结 在之前不会使用overlay机制的时候&#xff0c;我们想要做汽车标定&#xff0c;标定常量编译出来的地址一般都应该是ram的地址&#xff0c;而且在链接文件中都会指…

Django——orm模块创建表关系

django orm中如何创建表关系 1. 表关系分析 表与表之间的关系: 一对多 多对多 一对一 没有关系 判断表关系的方法: 换位思考用4张表举例: 图书表 出版社表 作者表 作者详情表图书和出版社是一对多的关系 外键字段建在多的那一方图书和作者是多对多的关系 需要创建第三张表来…

企业年会/年终活动如何邀请媒体记者报道?

​媒体邀约是企业或组织进行宣传的重要手段之一。通过邀请媒体参加活动&#xff0c;可以增加活动的曝光度和知名度&#xff0c;吸引更多的关注和参与。同时&#xff0c;媒体报道还可以提高企业或组织的权威性和可信度&#xff0c;从而让公众更容易接受其传达的信息。 企业年会或…

比较PID控制和神经网络控制在机器人臂上的应用

机器人臂是自动化领域中常见的机器人形式&#xff0c;其精确控制对于实现复杂任务具有重要意义。在机器人臂的控制中&#xff0c;PID控制和神经网络控制是两种常用的控制方法。本文将比较PID控制和神经网络控制在机器人臂控制方面的应用&#xff0c;包括控制原理、优缺点以及在…

Linux 多线程控制详解

目录 多线程编临界资源访问 互斥锁 API 简述 初始化互斥量 互斥量加锁/解锁 互斥量加锁(非阻塞方式) 互斥量销毁 程序示例 多线程编执行顺序控制 信号量 API 简述 初始化信号量 信号量 P/V 操作 信号量申请(非阻塞方式) 信号量销毁 程序示例 条件变量 创建和销毁…

分享一个JavaScript后台管理项目超实用的提示框

目录 新建js文件 设置css样式 html布局 script代码 调用方式 展示效果 新建js文件 首先我们需要新建一个js文件夹&#xff0c;将下方代码丢进去 "use strict";function _typeof(obj) { "babel/helpers - typeof"; if (typeof Symbol "f…

C/C++输出硬币翻转 2021年6月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析

目录 C/C硬币翻转 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 C/C硬币翻转 2021年6月 C/C编程等级考试一级编程题 一、题目要求 1、编程实现 假设有N个硬币(N为不大于5000的正整数)&#xff0c;从1…

【Linux】tree命令的独特用法

有关tree命令&#xff0c;我们只知道它可以将文件目录以树状图的形式展示&#xff0c;但其实还有很多有意思的功能可以使用。 一、tree命令的安装 各linux版本不同&#xff0c;但软件包名字就叫tree&#xff0c;直接安装即可 ubuntu&#xff1a; apt install tree centos&a…

rust实现quic服务端和客户端

演示如何使用 Quinn 库实现一个简单的 QUIC 客户端和服务器。QUIC 是一种基于 UDP 的协议&#xff0c;用于在互联网上进行快速和安全的通信。 在程序中&#xff0c;使用了 Rust 的标准库中的 error、net 和 sync 模块&#xff0c;以及第三方库 tokio 和 quinn。程序使用了 asy…