数据类型设计_数据的概念

前言

        笔者前面做过一个专栏叫"数据类设计",描述了用于界面的几个类型---矩阵图形类和像素图形类的写法.这里将把一些实用的类型设计,以及思路做一个较为精华的专栏.

        本贴对数据进行一个简单回顾,从机器层面和高级语言层面做个对比

程序设计中数据的重要性

        回顾经典公式"程序=数据结构+算法".算法表达的是一种由处理数据带来的逻辑.算法可以简单理解为"函数",他有两个层面的内容:逻辑层面和物理层面.在逻辑上他给需要表达的逻辑留出接口,使用者传入数据(或者无数据传入),达到自己的目的(可能有返回值也可能没有).在物理层面上,函数最终转化成机器指令,由芯片(底层电子电路)完成函数的执行.函数代表"功能",可以层层封装,直到芯片指令集.指令集的内容简单理解成"分支"---if else;"循环"---for,while;"计算"---加减乘除;"比较"---大于,小于,大于等于,小于等于,等于,不等于.所有的功能都是在这些基本指令上封装而成.是不是有些眼熟,是的,C语言的基础语法里有这些内容.

=============================内容分割线↓===================================

        自己开发算法行不行呢?也是可以的.大概你自己写一个函数,如

//伪代码
void do_something(){
    .....            //做一些什么事,产生某些结果
}

        别人调用这个函数,会发生一些什么事.---这样说是很抽象,但不管哪一本工具书中,每个说明功能的函数:告诉你传入什么数据,得到什么结果,这些都是封装了指令的函数.

        可以试想一下算法开发需要访问指令集或者硬件接口.和指令集打交道,明显要访问内存中某个位置(指令集放在内存中某个地址开始的一片空间中),而与硬件打交道,需调用硬件接口所在的文件.打个比方,C语言标准输出printf函数

printf("Hello World");

        这句代码执行后,在IDE(例如Visual Studio)中黑乎乎的输出窗口会出现"Hello World"字符串.如前所述,字符是一张像素图(Pixel_map),字符串本质上是一个像素图的集合.printf函数设计,需要识别每个字符,再到图集中搜索字符对应的像素图,放到输出窗口中.像素图(a,b,c.....)又来自哪里呢?可能来自键盘驱动或者操作系统自带,并加载到内存中备用.

        总的来说,算法开发考虑:调用指令集,调用硬件接口,直接访问内存.

        以上是笔者个人一些思考,不保证准确和完整.

=============================内容分割线↑===================================

        大部分的程序员不用自己开发算法,建立自己的逻辑(写函数)封装已有的函数.而设计数据是主要任务.

数据在底层(硬件)中的表示

笔者前面的帖子多次提到的,硬件层面的数据有两个基本性质:

        1.数据包括"地址"和"值"两个部分,地址用于传递值和修改值,值用于表示数据的含义.

        2.机器指令(硬件层面的指令)一次处理的数据量有限制:小于或等于一个字长单元.这意味着超过一个字长单元的数据,需要地址+偏移来访问.例如高级语言层面的一个复杂类型数据,或者数据集合,必须被分拆为多个字长单元以内的数据,逐个访问.

        因此硬件在访问和处理数据时,关注的有:数据起始地址,数据的大小,指针的偏移量.笔者的一篇帖子https://blog.youkuaiyun.com/jllws1/article/details/154231086?spm=1011.2124.3001.6209里有较为详细的讲解.

底层数据和数据类型

        本专题的目的是如何设计数据类型,值得一提的是,底层不懂什么是数据类型

硬件不知道什么是数据类型

        数据类型是高级语言中定义,方便程序员表达而设立的---当建立两个不同数据类型的对象,写程序的人和看程序的人主观上很容易区别他们是不同的.芯片不认识数据类型,只认识数字.这一点在C语言中有所体现,有句话是:C语言没有严格的类型检查.例如

#include<stdio.h>

float caculate(float value) {
	value += 2;
	return value;
};

int main() {
	int a = 1;
	float b=caculate(a);
	printf("%f\n", b);
	printf("%d\n", b);
}

        运行结果:

        将int类型数据a传入float类型形参value,编译过程不会报错.将float类型数据b在printf函数交给%d去解释,也不会报错(虽然结果可能不是预想的那样).C语言不会检查数据类型,而是完全把数据当二进制数看待.这同时意味着C语言程序员需要自己做类型检查,以保证代码正确.

硬件怎样检查数据类型

        C语言没有类型检查,但C++有类型检查,那么如何在机器层面实现呢?

        从"芯片只认识数字"这个前提去推导,在生成数据对象和传数据给形参的时候,加上一个数字做识别.例如

//C++代码
struct Person{
    string name;
    int    age;
}

Person xl("xiaoli",30);    //生成一个叫小李的对象

//显示对象的内容
void show(Person ps){
    cout<<ps.name<<endl;
    cout<<ps.age<<endl;
}

        在机器层面生成对象"小李"的时候,给个编号如17.在函数show编译的时候,给形参ps加个编号17,当调用show函数时,将传入的数据对象和形参类型做对比,如果对不上则编译报错.

        由此可以推导出C++的代码编译后比C语言会多一些,数据检查时要占用一些空间.

=============================内容分割线↓===================================

笔者简单分析数据类型如何用数字表示,每一种类型用一个数字来表示,假设基本数据类型如下

数据类型类型编号
char1
short2
int3
long4
float5
double6
基本类型表

对于上述的类型Person,单独用一张表

数据类型数量
charn
int1
Person类型表(类型编号17)

        其中n表示指针,即char *类型,若干个字符,当生成对象xl时,n等于7("xiaoli"6个字符加末尾一个空白符),而int数量等于1,表示只有一个int型的数据对象.

        尽管笔者不确定底层是不是这样表示,但这种操作是可行的.有<数据结构>作基础,所有的数据都可以用指针表示,反映在表中数量那一栏就是n.生成数据后,n的值将被确定.

        若把类型表放在一个地方存储起来,用一个动态数组存储表的元素个数,例如这里的Person是2.那么用一个类型表指针(假设Ptable)指向这个表,当从Person类型想要获得类型编号为18的类型的数据时,指针偏移2.

vector<int> des={.,.,..(前16个类型的元素表达),2(第17个类型的元素个数),..(第18个类型的元素个数)......以此类推}

             Ptable→数据类型数量
自定义类型前16//
//
//
//
Person类型(17)charn
int1
       第18种类型//
//

链表表示和二叉树表示:

数据类型数量数据类型数量
charnsometype1
int1Btreen
PersonnBtreen
Person类型表17Btree(二叉树类型)

       笔者不知道这个n在机器层面该怎么表达:).试想一下用字长单元最大数,比如16位,使用65535,32位使用42亿多那个数.原因是几乎用不到,一个数组如果太长就会使用其他数据结构例如散列结构分层表示,将在后续贴中有所涉及.

类型表扩展作用

        类型表还有个作用,计算数据占用空间.例如数据被放入某个文件中,建立一张表填入数据个数(递归到基本数据类型),计算空间作为指针偏移量.假设有17个自定义类型数据被放入一个文件1.data中,每个类型的数据写一张表,以Person为例:

序号文件中序号类型1数量类型2数量占用空间序号占据空间
120char7int11115
230char2int52228
Person类型空间占用表文件地址偏移表

        上面右边"文件地址偏移表"由多张左边表组成.当访问某个数据,例如文件中序号20的Person类型数据时,查找左边第1到19序号的占据空间值相加,得到的值是偏移到数据20的字节偏移,交给文件指针相加,即指向准确位置,进而访问到数据20内的数据(7个char和1个int)

        以上是发散思考

=============================内容分割线↑===================================

数据在高级语言中的表示

        数据在高级语言中必然有数据类型,当生成数据时必然有标识符,也是变量.

高级语言中数据分类

        1.基本类型,如int,float,char,short等

        2.基本类型的集合,如vector<int>等.

        3.复合类型,包括1和2在内的类型,也包括其他复合类型,例如

struct Student{
    string         name;         //名称
    int            age;          //年龄
    vector<long>   phone_number; //手机号(多个)
}

        4.复合类型的集合,如vector<Student>.

注意:第1种基本类型也称为简单数据类型,2,3,4类型都属于复杂数据类型.3和4可以交叉没有界线.

        这里面有面向对象,也有数据结构和算法的内容.本专题后续内容重点是在这一部分.

和硬件中数据的联系

        变量相当于给"值"取了个名字,方便理解.高级语言中的"取地址"操作也是针对变量.

        硬件中的数据是一种物理表达,偏向于空间大小;高级语言中的数据是一种逻辑表达,偏向于理解.

        复杂数据类型对象的访问和修改,也必须拆分成多个字长单元对象,逐个访问.程序员的工作大部分是在处理复杂数据类型对象使之满足要求,被戏称为搬砖.其实那一块块砖就是数据.

小结

       对计算机"数据"概念的一些理解

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重庆彭枫

你的鼓励是我创作的动力,谢谢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值