• 第7章:数据类型——《实践之路》笔记



    大多数语言有表达式,对象的类型两个概念

    类型为操作提供了隐式上下文环境

    如传递给函数类型根据类型重载函数

    类型支持实现了一部分接口限制了程序中可执行操作的集合
    好的类型捕捉无意义操作导致的错误

    7.1类型的意义与作用
    7.2类型等价与相容
    7.3-9复合类型的语法,语义,实现

    7.10对象相等,对象赋值

    7.1类型系统
    硬件 用不同方式 解释 存储器上的 一组二进制位
    解释为:指令地址字面量(字符,数字)
    二进制位本身无类型
    标识符——地址——值(二进制位)

    高级语言将值与类型相联系,提供上下文信息错误检查

    类型系统包括:
    定义类型,与特定语言结构相关联
    一组类型等价,类型相容,类型推理规则

    具有类型的结构:有的,或引用值的 结构
    结构包括:命名常量,变量,记录域,参数,(有时)函数
    及包含这些结构的表达式

    类型等价:两个类型相等的条件
    类型相容:一个类型支持另一个类型的接口
    类型推理:确定表达式的值,部分类型运算后得到的值的类型指定

    多态性变量参数的语言中,区分引用的类型  被引用的对象的类型

    引用——类型——对象

    两两打包

    同一名字不同时刻可能引用不同类型对象

    不能动态创建子程序 且用静态作用域的语言中,编译器总能确定名字引用的子程序,保证正确调用

    7.1.1类型检查
    保证程序遵守语言的 类型相容性规则
    违背:类型冲突

    强类型禁止操作应用不支持操作的对象。不发生强制??
    静态类型化:强类型,且所有(退一步:大多数)检查在编译时间执行

    检查操作——检查类型

    类型的来源:声明,或推理

    携带类型信息:引用携带,值携带

    C语言漏洞:联合,可变个数参数,指针和数组的互操作性
    不做运行时检查


    动态类型检查迟约束的一种形式


    python强类型化

    动态作用域规则:动态类型化
    因为编译器不知道名字引用了什么对象,无法知道其类型

    7.1.2多态性

    参数多态性,子类型多态性


    同一代码体可用于多个类型的对象
    需要运行时动态检查,对象是否实现了操作

    动态类型化 又称支持隐式的参数多态性
    运行时开销,推迟错误报告
    类型推理系统,通过静态类型化,支持隐式的参数多态性
    推断每个对象与表达式的类型
    编译器任务:对程序中对象静态确定一种 一致性的类型指派


    面向对象中,子类型多态性允许父类型引用子类型
    因为派生类要求支持基类的所有操作

    子——>转化——>父

    简单继承模型编译时实现类型检查
    使用这种实现的语言提供了显式的参数多样性泛型
    允许程序员定义带类型参数的类
    泛型用于集合

    python检查推迟到运行时

    编译时推断
    运行时跟踪


    7.1.3 类型的含义

    编译时推断
    运行时跟踪
    除此之外,

    声明对象的类型,

    声明非内部类型的特征

    指称
    构造
    基于抽象
    观点

    指称:一个类型是一组值(域)
    属于值集合——对象属于类型

    构造:类型:由内部类型 迭代 构造出的复合类型

    抽象:类型是一个接口,由一组定义良好的相互协调语义操作组成

    指称语义学:一组值:一个论域:一个类型
    表达式:论域中的一个值
    函数:一个存储映射到另一个存储
    存储:名字的映射
    赋值:赋值前内容映射到赋值后内容

    可以基于集合上的数学运算,描述用户定义类型


    枚举类型:一组值


    7.1.4类型分类

    内部类型:处理器硬件支持的类型
    整数,字符,布尔,实数

    离散类型:可数有序——枚举,子界


    标量类型:简单类型


    枚举类型:一组命名元素
    排序比较前驱后继枚举控制
    整数相容性不定

    子界:离散基类型的连续子集
    编译器分析子界的声明,动态检查越界

    复合类型:结构类型:非标量类型

    记录:一组域,各域类型笛卡尔积

    变体:各个域类型并集

    数组:下标元素映射成员类型

    集合基类型的数学幂集

    指针:左值,直接用地址实现
    用于实现递归的数据类型

    (链表):没有映射与下标。长度可变

    文件:位于大规模存储设备内存之外的数据,
    当前位置的概念,在顺序操作隐式使用下标
    反映了物理设备固有特性,如顺序访问


    7.1.5正交性
    高度正交的语言,容易理解,使用,
    容易做形式化的推理

    C消除语句表达式的差别?提高正交性
    语句只为提供值:返回空类型(如函数返回值void

    数组元素类型,数组下标多样性:正交性体现

    非正交性:数组的长度要求编译时确定

    复合文字量聚集值:JS对象字面量
    用于静态数据结构初始化/赋值


    7.2类型检查
    大多数静态类型的语言中,定义对象时必须指定类型
    对象出现的上下文也是有类型的(上下文究竟是什么?)

    上下文:对象周围环境对对象的要求、期待?作用于对象的规则要求?
    语言包含了规则,限制了上下文中可以合法出现的对象类型:上下文文法?

    类型相容:正确,弱于类型等价的要求
    类型变换,类型强制非变换转换

    类型推理:子表达式类型——整体类型

    7.2.1类型等价

    结构等价:成分相同
    名字等价:每个定义的类型只与自身类型相等。新语言的选择


    结构等价:低级的,基于实现
    潜在区别
    域的声明顺序

    编译器递归展开定义——类型名序列
    递归与基于指针的展开


    名字等价:既然定义了两次,则,定义的是不同的类型语义

    类型别名
    严格名字等价:别名类型互不相同
    宽松

    严格,宽松的区别——声明定义的区别???
    type A=B
    严格:这是定义
    宽松:这是声明


    类型变换转换

    期望实参形参类型匹配:相同,相容(转化后相同)

    显式类型转换:
    1.结构等价,名字不等价
    2.不同值集合有交集判断是否为交集情况,否则报错
    3.不同的底层表示,处理器用于变换的机器指令。存在信息损失算数溢出

    非变换类型转换:临时值
    颠覆了语言的类型系统,绕过检查机制
    强制上下文相容

    7.2.2类型相容
    类型等价——上下文相容

    运算符:运算对象支持 公共类型,对公共类型操作


    实参 相容于 形参
    返回值

    C 类型双关,指定方式解读二进制位

    自动隐式变换:类型强制
    强制也可能需要动态类型检查(复合?继承?),或底层表示间变化

    强制削弱了语言安全性

    C混用数组与指针

    趋势:静态类型化,远离类型强制

    重载:一个名字,不同对象
    上下文信息解析

    强制:一个对象,不同类型
    匹配规则

    文字字面常量:重载的

    通用引用类型:可保存任意类型对象的引用
    为写出通用的容器

    c void*
    java c# object

    当赋值给特定引用类型对象时,保持类型安全性

    通用类型到专门类型的 赋值合法性
    更普遍问题——保证任意赋值的合法性

    解决方式:

    对象具有自描述——面向对象语言

    值模型:指针类型与引用对象类型

    引用模型:值自带类型

    名字——地址——值

    类型解释地址中的值


    需要动态 方法约束?(为子类选择合适的父类方法继承)

    类型强制,产生合适异常

    容器类型,保存通用引用类型对象
    通用引用类型对象:与对象本身属性无关

    没有类型标志的语言
    不可能检查赋值时的类型转变
    凭借不检查的类型转换

    表达式的类型
    运算符结果运算符类型(函数签名)
    函数调用结果:函数声明返回类型
    赋值结果:左值类型

    内部运算符——内部数据类型
    内部运算符——复合类型

    声明对象类型
    字面量推断类型
    类型不确定——多态

    7.3记录(结构),变体(联合)
    记录:不同类型,相关数据 打包成整体

    c++ struct class 成员可见性区别

    域:记录中成员
    访问域:.运算符

    C++允许结构标记作为类型名
    不需要struct前缀
    实现为typeof语法糖

    嵌套记录域

    存储布局
    编译器 符号表 保存每个记录类型中 各个域的偏移
    访问域:位移寻址,加载/存储

    局部对象:基址寄存器:帧指针,位移值:偏移量之

    内存空洞
    压缩:未对齐:优化空间,降低速度

    记录赋值
    相等比较空洞一致填充(0) 或按域比较
    折中方案:对齐条件排序域
    重排的优点:需要频繁访问的域集中在一起:同一缓存行空间局部性
    重排只是个实现问题,可以指定对齐方式

    with语句
    pascal:省略引用

    python:添加作用域?

    变体(联合):共享内存相同字节
    系统程序:同一字节不同时刻不同解释
    意图:彼此用于不相关的目的:数据不同时存在


    非转换类型强制显式绕过语言的类型系统

    继承:代码重用,内存重用类型安全

    7.4数组
    下标类型成员类型的映射

    正交性:
    下标可选类型
    成员可选类型
    成员是否必须同类型

    非离散下标:关联数组散列表
    字典类型相似

    离散的下标:允许连续的内存分配高效
    定长:更高效

    声明
    构造符
    字面量赋值

    7.4.1语法与操作

    []运算符,返回引用显式左值
    否则,get,set

    多维数组
    数组的数组
    切片支持

    c:指针与数组之间的集成导致不支持切片?

    数组运算

    7.4.2维度个数上下界,分配

    声明描述形状
    静态形状:栈中分配
    动态形状:堆

    加工不知道形状,或动态改变

    加工???
    分配空间,生成形状信息支持索引

    编译的语言:可以允许上下界动态,通常要求维度个数静态

    内情向量运行时 保存形状信息


    内情向量
    编译期间  符号表  维护每个数组的维度与边界信息
    每个记录:域偏移量
    如果数组维度数目边界在编译
    已知:符号表中找出,计算数组元素的地址
    未知:生成代码,运行时从内情向量中查找

    内情向量包含:每个维度的下界
    除最后一维外的各维度大小最后一维大小=元素类型大小
    包含每个维度的上界,如需动态语义检查下标越界
    下界可推导出上界,保存上界:避免反复运算

    内容在加工时,或维度数目,上下界变化初始化
    赋值语句可能需要复制内情向量

    栈分配
    子程序参数动态形状数组
    静态数组——传参给动态数组,生成内情向量


    局部数组形状加工时固定
    帧栈分为固定大小区可变大小区(保存指针与内情向量)
    加工时???

    任意时刻改变大小(形状)完全动态
    改变的顺序栈的进出顺序不一致
    必须在堆中分配

    完全动态但维度静态可知
    帧栈上放置指针+内情向量

    维度也可变
    内情向量放在堆上堆的开始处。避免重复复制???

    废料回收
    退出栈回收堆上分配的内存空间

    7.4.3内存布局
    行优先列优先
    内存布局方式:影响迭代顺序
    缓存效率缓存缺失

    行指针布局:java

    允许不规则数组(字符串数组)
    加快访问元素
    间接访问/地址计算

    连续布局地址计算
    寻找计算中的编译时常数
    公共表达式
    地址计算中的动态部分——部分信息编译已知——转化为静态部分

    静态消除检查:特别是枚举控制的

    C数组维度上的下标下界为0
    数组与指针的互操作性

    7.5字符串

    换意序列:增加一位,扩充字符集

    字符串是一维的,不包含引用


    7.6集合
    公共类型任意数目
    基类型:元类型
    位向量:元素个数少
    散列表
    数组,散列表,树


    7.7指针与递归类型

    指针:值是引用(对象地址)的变量

    指针与递归类型

    指向指针的指针

    递归类型:包含 本类型对象的引用
    用于构造链式结构:表,树,图

    引用模型:每个对象都是引用
    容易实现递归

    值模型:需要指针概念,值为其他对象的引用

    指针:高级概念,特定对象的引用
    地址:低级概念,内存单元的位置

    显式回收:语言实现简单
    自动回收:区分废料与活动对象

    指针操作:
    堆中对象的分配、释放间接操作:访问引用的对象,赋值重载运算符

    java:内部对象值模型,自定义对象引用模型

    需要相互引用:编译器中符号表的记录 语法树的节点~~

    C没有可用于连接数据结构的聚集值写法

    分配内存:

    c: malloc 库函数,返回void*
    c++:new 类型安全

    访问指针引用的对象:显式的间接运算符

    c指针,数组
    无下标数组名自动转换——指针:数组第一个元素
    传递数组,传递指针

    下标运算基于指针运算定义:自举,语法糖

    指针+-整数,指针-指针,比较

    加工时需要分配空间!!!!
    数组:整个数组空间
    指针:一个指针空间

    指针:使得两个左值的别名判断变难

    声明必须使编译器确定元素大小,等价的,指针引用对象的大小

    sizeof字节数
    编译时计算,除了可变长数组


    悬空引用:活动指针 不再引用合法对象,可能破坏堆栈结构
    指向栈内局部变量的指针
    多个指针同时指向,一个指针显式回收,剩余指针

    指针和被引用对象都可能作为实参传递???后果

    废料收集:
    消除了检查悬空引用的必要性

    引用计数
    对象无效:不存在指向它的指针
    递归地工作


    java:显式创建 作用域存储区域,线程不再访问,整体回收

    正确识别指针的位置

    只有在语言强类型情况,引用计数工作

    无法回收循环引用结构???

    追溯式收集:

    废料:堆外不可访问的对象

    理想:不会再使用的对象

    堆外指针出发:递归遍历探查堆,确定有用的东西(标记),清扫

    必须找到所有指针块开头放置类型描述符

    遍历:栈——无可用空间

      隐式栈:指针反转用于回溯

    标记好翻转的指针,每个时刻只有一个指针翻转?

    图图图!

    停顿并复制

    堆分为两个区间:一个区间分配,满,压缩到另一个区间,语义交换

    实际使用虚拟空间,不会造成浪费

    分代式收集

    最动态的是最短命

    存活久的先保留着

    ???废料不再访问,为何保留???

    保守式收集

    在全局与栈中扫描按字对其的量,分析是否包含堆中地址

    看着像指针的,都保留着指向的地址

    需要程序员不隐藏指针指针转换为其他类型

    不能做压缩???

    7.8表

    表:
    递归定义的结构:
    空,
    有序对:对象(原子),表

    成分 构造
    提取 成分

    判断
    长度
    索引
    翻转
    匹配
    应用函数构造新表

    7.9文件 IO

    交互式IO,依赖顺序

    文件:程序地址空间外的存储器OS实现
    临时文件:因为内存放不下
    持久文件:读写存数据

    file数据类型

    7.10相等性检测,赋值
    赋值需要相等性检测,赋给自身

    别名
    引用相同(地址相同)
    值相同

    相等定义:归结于左值右值的区分
    比较左值:比较地址
    引用同一对象浅比较

    比较右值:比较
    深比较

    赋值
    赋值:复制引用
    赋值:复制副本,值

    复合对象的比较:递归比较

    复合类型
    类型大小形状
    数组大小形状

    自定义类型

    自定义比较

  • 相关阅读:
    APDU:APDU常用指令
    其他:IntelliJ IDEA设置运行内存
    Linux:获取Linux离线postgresql数据库安装包并部署
    资源:Postgresql数据库下载路径
    免费版:Xshell和Xftp下载路径
    Raspberry Pi:树莓派开发板配置USB启动系统
    Raspberry Pi:树莓派安装基础系统 Raspberry Pi(树莓派系统)
    Raspberry Pi:树莓派安装Kali2021新版本
    Docker:虚拟机挂起后,再启动docker容器连接失败
    Docker:docker搭建redis一主多从集群(配置哨兵模式)
  • 原文地址:https://www.cnblogs.com/qmcj/p/9108188.html
Copyright © 2020-2023  润新知