您的位置:首页 > 理论基础

各种数值计算机内存的存储规则、补码计算、内存数据位扩展和具体意义、关于位运算

2012-04-09 20:51 441 查看
//关于数据在计算机内存中的存储:无论什么数值,也无论这个数值是用什么进制表示,计算机存储的都是这个数值的补码。
//如果表示这个数值的时候,前面有+号或者没有加符号,则认为是正数,这个时候就是把这个数值转换为二进制后直接存入计算机,因为正数的补码就是其本身(注意:存储的时候只会看有没有加+号来标识,而不看其实际意义,如(int)x80000001前面没有加符号,则默认其是一个正数,尽管它最高位是并且如果看成正数则实际上已经越界,在存入计算机的时候也会当做正数来计算补码然后存入计算机,这一点可以通过查看memory来证实,内存中也是存储的x80000001);
//如果表示这个数值的时候,前面加了-号来标识这是一个负数,则需要先转换成二进制再按照计算负数补码的步骤变换成补码再存入计算机内存,(注意:存储的时候只会看有没有加-号来标识,也不看起实际意义,如(int)-0x80000001是一个负数,尽管这个数值已经没有实际意义,因为如果将后面看做一个正数实际上已经越界,整体上如果看成负数也已经越界,但是计算机会计算它的补码,然后存入内存这一点可以通过查看memory来证实,内存中存储的是x7fffffff

//关于补码的计算规则:以前一直是将原码除符号位逐位取反,然后末位加得到补码,但是这样-0x80000001得到的补码应该是xffffffff,但是实际查看得到的是x7fffffff。所以应该是,将-号后面的数只管展开成正数的二进制形式,如果不够所需的类型的长度前面补零,如果超过了将超出的位数舍弃,然后除了所需类型的最高符号位之后的都逐位取反末位加,最后将符号位加,溢出的位舍去,这样-0x80000001的补码计算之后得到的就是x7fffffff。这个补码的计算方法可以通过计算short类型的-0x18001来得到确认(开始的时候推测是将-0x80000001扩展成了long之后求补码截断所得,但是通过求sizeof(0x80000001)得到的是否定了这种假设)。

//关于数值类型扩展:当需要把一个短类型转换成一个长类型的时候,需要先将数值转为补码形式,然后通过位扩展来进行,在位扩展的时候,只看需要扩展的数值的符号位,如果是则将符号位之前填充即可,如果是1则填充1需要将一个长类型转换成一个短类型的时候,先将这个数值表示为补码形式,然后从后向前截取需要的位数即可。。

//关于数值的表示:输出的数值表示的意义是由数据类型决定的,是内存中数据格式化为特定类型数据时候所具备的意义的体现。内存中同样一个x80000000,输出为unsigned
int和输出为int则表示的是完全不同的两个数值。

//关于位运算:C++中的位运算都是针对在内存中存储的位的具体形式而言的。对于一个正数x,x^0xffffffff和x^-1的效果是完全相同的。这就是因为xffffffff是正数,补码存入到内存还是xffffffff;而-1是负数,但是补码存入内存中也是xffffffff;所以二者运算效果是完全相同的。其效果就是~a即将a按位取反(这个结果也是内存存储形式,具体意义需要有数据类型来格式化),另外位运算一般都是使用unsigned无符号数进行运算。

#include <iostream>
using namespace std;

int main()
{
//关于数据在计算机内存中的存储:无论什么数值,也无论这个数值是用什么进制表示,计算机存储的都是这个数值的补码。
//如果表示这个数值的时候,前面有+号或者没有加符号,则认为是正数,这个时候就是把这个数值转换为二进制后直接存入计算机,
//因为正数的补码就是其本身(注意:存储的时候只会看有没有加+号来标识,而不看其实际意义,如(int)0x80000001前面没有加符号,则
//默认其是一个正数,尽管它最高位是1并且如果看成正数则实际上已经越界,在存入计算机的时候也会当做正数来计算补码然后存入计算机,
//这一点可以通过查看memory来证实,内存中也是存储的0x80000001);
//如果表示这个数值的时候,前面加了-号来标识这是一个负数,则需要先转换成二进制再按照计算负数补码的步骤变换成补码再存入
//计算机内存,(注意:存储的时候只会看有没有加-号来标识,也不看起实际意义,如(int)-0x80000001是一个负数,尽管这个数值已经没
//有实际意义,因为如果将后面看做一个正数实际上已经越界,整体上如果看成负数也已经越界,但是计算机会计算它的补码,然后存入内存
//这一点可以通过查看memory来证实,内存中存储的是0x7fffffff

//关于补码的计算规则:以前一直是将原码除符号位逐位取反,然后末位加1得到补码,但是这样-0x80000001得到的补码应该是0xffffffff,但是
//实际查看得到的是0x7fffffff。所以应该是,将-号后面的数只管展开成正数的二进制形式,如果不够所需的类型的长度前面补零,如果超过了
//将超出的位数舍弃,然后除了所需类型的最高符号位之后的都逐位取反末位加1,最后将符号位加1,溢出的位舍去,这样-0x80000001的补码计
//算之后得到的就是0x7fffffff。这个补码的计算方法可以通过计算short类型的-0x18001来得到确认(开始的时候推测是将-0x80000001扩展成了long
//之后求补码截断所得,但是通过求sizeof(0x80000001)得到的是4否定了这种假设)。

//关于数值类型扩展:当需要把一个短类型转换成一个长类型的时候,需要先将数值转为补码形式,然后通过位扩展来进行,在位扩展的时候,
//只看需要扩展的数值的符号位,如果是0则将符号位之前填充0即可,如果是1则填充1;需要将一个长类型转换成一个短类型的时候,先将这个
//数值表示为补码形式,然后从后向前截取需要的位数即可。

//关于数值的表示:输出的数值表示的意义是由数据类型决定的,是内存中数据格式化为特定类型数据时候所具备的意义的体现。
//内存中同样一个0x80000000,输出为unsigned int和输出为int则表示的是完全不同的两个数值。

//关于位运算:C++中的位运算都是针对在内存中存储的位的具体形式而言的。对于一个正数x,x^0xffffffff和x^-1的效果是完全相同的。
//这就是因为0xffffffff是正数,补码存入到内存还是0xffffffff;而-1是负数,但是补码存入内存中也是0xffffffff;所以二者运算效果
//是完全相同的。其效果就是~a即将a按位取反(这个结果也是内存存储形式,具体意义需要有数据类型来格式化),另外位运算一般都
//是使用unsigned无符号数进行运算。

cout << sizeof(-0x80000001) << endl;
cout << sizeof(-0x180000001) << endl;
int x=0x80000001;   //0x80000001
int y=-0x80000001;  //0x7fffffff
cout << x << endl;
cout << (unsigned)x << endl;

short sx=0x18001;   //0x8001
short sy=-0x18001;  //0x7fff

//下面两行代码得到的结果应该是不同的,尽管初始值是一个数字
int z=sy;         //这个是截断之后成short的扩展
int m=-0x18001;   //这个则是正常的int类型
cout << z << endl;
cout << m << endl;

short sz=-32769;
cout << sz<< endl;

cout << (-3^-1) << endl;  //2

return 0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐