深入理解计算机系统之数据的表示与存储

来源:互联网 发布:生死狙击卖号淘宝店铺 编辑:程序博客网 时间:2024/04/28 04:24

前言

在编写程序的时候,不同数据类型进行转换和计算的时候总是可能出现各种各样奇怪的bug,所以深入的了解计算机系统中数据的表示与存储有利于我们编写高效与健壮的计算机程序,本文主要总结计算机系统中整数,浮点数的表示和存储。

真值与补码的相互转换

真值指的就是现实当中的正负数,而补码是计算机中表示真值的一种编码方式,也就是0/1编码的序列。


补码与真值的关系如下:

这里写图片描述 
其中n表示机器的字长,X是真值。


求真值的补码

正数的补码为其本身,负数的补码为正数的原码各位取反加1,简便的方法为从右到左遇到的第一个1的前面各位取反。

如:假设机器数为8位,+123的补码为01111011,-123的补码为10000101。


求补码的真值

公式为:

这里写图片描述

例子:

这里写图片描述

简便求法:

符号为0,则为正数,数值部分相同,符号为1,则为负数,数值各位取反再加1.

如:01010110的真值为1010110=64+16+4+2=86. 11010110的真值为-0101001=-(32+8+2)=-42.


整数的表示

整数分别无符号数和带符号数,带符号数中编码的最高有效位为1代表为负数,为0代表为整数。对于C编译器,如果一个表达式同时存在无符号数和带符号数,则会将带符号数强制转换成无符号数。无符号数通常在一个数的后面加一个”u”或者”U”。

如下面的例子:

这里写图片描述

不同版本编译器在处理常量默认的类型是不同的:

这里写图片描述

特别注意的是2147483648这个值为2的31次方,在C90和C99的编译器中分别当成了无符号数unsigned int和带符号数long long处理,其范围是不一样的。

实例:

如C表达式-2147483648<2147483647的执行结果在不用系统的值可能为false也可能为true。因为如果在C90标准下,2147483648为unsigned int类型,则-2147483648<2147483647按照无符号数来比较,-2147483648变成无符号数为10…..0B比2147483647(01….1B)大,所以结果为false.而在C99标准中,2147483648被当做long long带符号数处理,所以-2147483648<2147483647的结果为true.同理下面的例子也同样可以得出结果。

int i=-2147483648;bool res=i<2147483647;//true,带符号数处理/>>>>>>>>>>>>>>>/-2147483647-1<2147483647;//true

程序验证:

#include <stdio.h>int main(){    int x=-1;    unsigned u=2147483648;    printf("x = %u = %d\n",x,x);    printf("u = %u = %d\n",u,u);    if(-2147483648<2147483647)        printf("-2147483648<2147483647 is true\n");    else        printf("-2147483648<2147483647 is false\n");    if(-2147483648-1<2147483647)        printf("-2147483648-1<2147483647 \n");    else if (-2147483648-1==2147483647)        printf("-2147483648-1==2147483647 \n");    else         printf("-2147483648-1>2147483647 \n");} 

在C90标准下的结果:

这里写图片描述


IEEE 754标准下浮点数的编码表示

单精度的编码方式如下:

这里写图片描述

S代表符号位:1代表负数,0代表整数。
Exponent代表阶码(指数),占8位。单精度规格化的阶码范围为-126~127,双精度为-1022~1023。
significand表示尾数部分。
表达式如下:

这里写图片描述

实例:

已知float变量x的机器数为BEE00000H,求X的值

BEE00000H=1|0111 1101|110 0000 0000 0000 0000 0000,由单精度格式有S=1,Exponent=0111 1101=125,Significand=110 0000 0000 0000 0000 0000。

则代入单精度表达式得真值为-0.4375。


已知float变量x的值为-1028,求X的值

-1028=-0100 0000 0100=-1.00 0000 0100B*2^10,因此S=1,阶码E=127+10=137=1000 1001,Significant=0000 0001 0000 0000 0000 000 .
则X=1100 0100 1000 0000 1000 0000 0000 0000=C4808000.


数值存储时的顺序-大端与小端

大端顺序指的是数据的最高有效数据存放于低地址。而小端顺序指的是数据的最低有效数据存放于低地址。

如一个数:0xFFFF0001其大小端存放顺序如下:

这里写图片描述

程序验证一个CPU的大小端方式

#include <stdio.h>int main(){    union NUM    {        //union的存放顺序是所有成员从低地址开始         int a;//4字节         char b;//1字节     }num;    num.a=0x12345678;    if(num.b=0x12)        printf("Big Endian \n");    else        printf("Little Endian \n");    printf("num.b = 0x%x \n",num.b);}

结果:

这里写图片描述


阅读全文
0 0
原创粉丝点击