参考:添加链接描述
我们所说的程序实际上由两部分组成:程序代码与程序数据。只有用机器码编写的程序(01代码)才能被机器识别执行,其他任何语言编写的程序都需要 “翻译”成机器语言才能执行,翻译”的这个工作就是编译器在做,编译器将源代码“翻译”成机器代码,然后处理成目标代码,通过链接器生成最后的可执行代码。
我们所说的计算机无非就是由输入输出设备、存储器、控制器、运算器等单元组成的,控制器将程序代码与程序数据的机器码从存储器中读取交给运算器执行,得到相应的结果。所以我们要存机器的角度看程序就需要知道我们的程序代码和程序数据在存储器中是如何存储的。
我们的源代码一般来说由两部分组成
1.程序代码语句
2.程序所需数据
对于第一种,编译器将按照C规则将其“翻译”成机器码所对应的操作指令;对于第二种也分为两种:
1.数值数据
2.非数值数据
对于数值型数据,C语言的基本数据类型分为,整形、浮点型、字符型、空类型,其他非基本数据类型的数据都是由基本类型构成的。那么这些数据在内存中是如何存储的呢
1.对于整形数 int short long 四字节、双字节、八字节,同时都有无符号的类型,有无符号在于高字节的最高位是否是符号位,如果是那么0代表正数,1代表负数;如果不是那么依然代表数据位。
整型数在内存中是以补码的形式存储的,正数的补码和原码、反码都相同;0的补码就是全0,包括符号位;负数的补码计算方法为:符号位不变,数置位取反然后加1。
机器码,反码补码等都是在特定字长下讨论的,如果计算有进位需要丢弃。
2.浮点数 float double 四字节、八字节。存储方式与整形不同,所有字节公用,对于float形,32位,分为s、e、f位,s占最高位1位符号位,e占八位位指数位,f为小数位23位。
以小数123.45为例:(小数部分转换不精确)
(123.45)D = (1111011.011100)B
那么s = 0(正数),E = 6, f = 0.111011011100,对于单精度来说e = E + 127,那么
e = 133 = (10000101),这个浮点数在内存中的存储方式就是:
01000010111101101110000000000000
对于双精度s符号位依然是1位,e指数位为11位,e = E + 1023,f位52位。
float 保证6位有效数字的精度,double保证15位的有效位数精度
3.对于字符型,也就是我们通常所说的非数值形数据,当然是由一些,西文字符,汉字等等组成,这些数据是通过编码来存储的,这里就有必要说一下文件的编码。
我们通常所说的编码大致分为ASCII码、Unicode码、GB码,其中Unicode码分为UTF-8、UTF-16、UTF-32等编码,就是表示单字符所用字节数不同,UTF-8编码和GB18030编码是兼容ASCII的(前127个字符),这两种也是最常用的。
ASCII是最初的编码,Unicode码扩展了世界各国的字符,GB编码是适用于中国的自己的一套编码。
在说几个概念:1.文件的编码格式。计算机中所有的文件都在磁盘中通过机器码存储,那么存储的编码格式就是这个文件的编码格式,这个是由文件生成的时候决定的,即文件自身的编码格式。2.系统环境的编码格式,这个主要是指要打开文件的系统,他是什么编码格式,他将按照自己的编码格式打开某个文件,如果文件的编码格式与系统环境的编码格式不同,可能导致乱码。3.对于C等程序性文件程序里面的字符串的编码格式,这个叫做程序内码,一般来说我们对于窄字符(char)用的都是ASCII码,但是程序中出现的宽字符(wchar_t)会按照Unicode来编码或者GB来编码(比如注释中的字符)。
对于第二点,对于Windows操作系统来说一般都是GB编码,对于Linux来说一般都是UTF-8编码,所以对于1来说,Window系统下生成的文件默认都是GB,儿Linux来说默认位UTF-8当然如果在生成文件的时候主动设置那就看设置成什么形式了。再来看我们的程序文件的内码,因为我们在程序中的窄字符用的都是ASCII又因为UTF-8和GB编码都是兼容ASCII的所以不管是在linux中还是在Windows中,我们的ASCII码字符串都会被当作是GB编码或者是UTF-8编码,与他的源文件的编码是一致的,这也是为什么我们在Windows下或者Linux下编写程序(源文件本身是GB或者UTF-8)程序中出现ASCII任然能正确编译运行的原因。(VC的运行环境是Windows,默认产生的文件是GB格式,gcc默认产生UTF-8模式)。
C语言中的字符型一般只有窄字符(char),一个字节,通过ASCII码表来存储各个符号所对应的ASCII码值(存储方式与整形的正数相同)使得计算机能表示各种符号等。