C语言的符号表和类型系统2

2024-04-30 22:48
文章标签 语言 类型 系统 符号表

本文主要是介绍C语言的符号表和类型系统2,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

阅读博客的朋友可以到我的网易云课堂中,通过视频的方式查看代码的调试和执行过程:

http://study.163.com/course/courseMain.htm?courseId=1002830012

这一节,我们继续就上一节讨论的内容,继续就符号表和类型系统的构建进行深入的探讨。

基于上一节的基础,我们看看,编译器如何为一个变量构建它在符号表中的记录和类型系统。假设我们的C语言代码中有如下的变量定义:

enum rabbits {
FLOSPY, MOPSEY, PETER
};

上面的枚举类型,会被C编译器转换成如下形式的C代码:

const int FLOSPY = 0;
const int MOPSEY = 0;
const int PETER = 0;

编译器在解析 “const int FLOSPY = 0” 这条语句后,会在符号表中产生以下数据结构:

这里写图片描述

由于变量FLOSPY 没有*, 没有[]之类的类型声明,因此它的类型系统只需要说明符,不需要修饰符,因此它的类型列表中就是由一个specifier.它的数据类型是INT, 由于被初始化成一个常量整形,所以constantValue设置为0.大家注意,从Symbol对象引出两个箭头,两个箭头都指向specifier对象。之所以需要两个箭头是因为,类型系统本质上就是一个链表,链表链接的是两种对象,一种是declarator, 一种是specifier, 我们在实现代码的时候,需要把declarator放在链表的前面,specifier放在链表的最末尾。因此从symbol发出的两个箭头,一个指向队列的开头,这样从这个箭头起始就可以逐个访问链表的每个对象,由于declarator放在链表的前面,这样从这个箭头开始,就可以访问一系列的declarator, 但是如果我们想要访问链表最末尾的specifier对象,那就得遍历整个链表,这样效率就太慢了,于是,从symbol对象引出第二个箭头直接指向链表的末尾,也就是specifier对象,这样想要直接访问类型系统链表的specifier,直接从第二个指针读取就可以了,不需要遍历整个链表,例如下面这个例子:

long int (*Frollo)[10];

编译器会给上面的变量声明建立如下的符号表记录和类型队列:

这里写图片描述

大家看到,类型系统队列有三个元素,前两个是declarator, 最后一个是specifier, 从symbol引出的两个箭头,一个指向链表的开始,第二个直接指向链表的末尾,也就是specifier.

这样,我们就需要在代码中,设计一个链表来讲declarator 和 specifier连接起来,这个链表的代码如下:


public class TypeLink {boolean  isDeclarator = true; //true 那么该object 的对象是declarator, false那么object指向的就是specifierboolean  isTypeDef = false; //true,那么当前变量的类型是由typedef 定义的Object   typeObject;TypeLink  next = null;public TypeLink(boolean isDeclarator, boolean typeDef, Object typeObj) {this.isDeclarator = isDeclarator;this.isTypeDef = typeDef;this.typeObject = typeObj;}public Object getTypeObject() {return typeObject;}public TypeLink toNext() {return next;}
}

这样我们在Symbol类中,要添加两个成员变量:

public class Symbol {String  name;String  rname;int       level;  //变量的层次boolean   implicit;  //是否是匿名变量boolean   duplicate;   //是否是同名变量Symbol    args;   //如果该符号对应的是函数名,那么args指向函数的输入参数符号列表Symbol    next;  //指向下一个同层次的变量符号TypeLink  typeLinkBegin;TypeLink  typeLinkEnd;
}
Struct 类型变量的类型系统

在Specifier 类中,最后一个成员变量StructDefine,我还没有解释,这个类型是专门用于处理Struct类型声明的。由于一个结构体里面包含了多种变量声明,所以结构体变量的存在使得类型系统复杂了很多,我们先看看结构体变量类型的代码:

/** struct argotiers {*     int  (*Clopin)();*     double  Mathias[5];*     struct  argotiers*  Guillaume;*     struct  pstruct {int a;} Pierre; * }*/
public class StructDefine {private String tag; //结构体的名称,例如上面的例子中,对应该变量的值为 "argotiers"private int  level; //结构体的间套层次private Symbol fields; //对应结构体里的各个变量类型public StructDefine(String tag, int level, Symbol fields) {this.tag = tag;this.level = level;this.fields = fields;}public String getTag() {return tag;}public int getLevel() {return level;}public Symbol getFields() {return fields;}
}

我们以一个具体的结构体声明例子为例,看看它对应的符号表和类型系统是怎样的:

struct  argotiers {int  (*Clopin)();double   Mathias[5];struct   argotiers *Guillaume;struct   pstruct {int a;} Pierre;
} gipsy;

它的类型系统如下:
这里写图片描述

这个系统看起来似乎很复杂,但实际上它是由若干个简单的类型系统结合而成的,搞清楚前面我们描述的类型系统队列,对这个图的理解应该不难,这个图其实也表明,任何复杂的的系统,都是由多个简单的单元相互勾连交叉所形成的。

这两节的代码主要用于解释概念,在实际开发时,我们会根据需要,对当前代码做相应修改,下一节,我们基于前面的变量声明解析过程,看看语句:
long int *x, y;

所声明的两个变量,他们的类型系统和符号表是如何建立的。

这篇关于C语言的符号表和类型系统2的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/950120

相关文章

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

在不同系统间迁移Python程序的方法与教程

《在不同系统间迁移Python程序的方法与教程》本文介绍了几种将Windows上编写的Python程序迁移到Linux服务器上的方法,包括使用虚拟环境和依赖冻结、容器化技术(如Docker)、使用An... 目录使用虚拟环境和依赖冻结1. 创建虚拟环境2. 冻结依赖使用容器化技术(如 docker)1. 创

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型

CentOS系统Maven安装教程分享

《CentOS系统Maven安装教程分享》本文介绍了如何在CentOS系统中安装Maven,并提供了一个简单的实际应用案例,安装Maven需要先安装Java和设置环境变量,Maven可以自动管理项目的... 目录准备工作下载并安装Maven常见问题及解决方法实际应用案例总结Maven是一个流行的项目管理工具

Go语言利用泛型封装常见的Map操作

《Go语言利用泛型封装常见的Map操作》Go语言在1.18版本中引入了泛型,这是Go语言发展的一个重要里程碑,它极大地增强了语言的表达能力和灵活性,本文将通过泛型实现封装常见的Map操作,感... 目录什么是泛型泛型解决了什么问题Go泛型基于泛型的常见Map操作代码合集总结什么是泛型泛型是一种编程范式,允

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

C语言小项目实战之通讯录功能

《C语言小项目实战之通讯录功能》:本文主要介绍如何设计和实现一个简单的通讯录管理系统,包括联系人信息的存储、增加、删除、查找、修改和排序等功能,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录功能介绍:添加联系人模块显示联系人模块删除联系人模块查找联系人模块修改联系人模块排序联系人模块源代码如下

Redis的Zset类型及相关命令详细讲解

《Redis的Zset类型及相关命令详细讲解》:本文主要介绍Redis的Zset类型及相关命令的相关资料,有序集合Zset是一种Redis数据结构,它类似于集合Set,但每个元素都有一个关联的分数... 目录Zset简介ZADDZCARDZCOUNTZRANGEZREVRANGEZRANGEBYSCOREZ