标签:
本节研究信息表示中关于数值的相关问题;
代码片段如下:
int x = 0x10203040; char* p = (char*)&x; printf("%p %p %p\n", &x, p, &p); printf("%x %p %p\n", p[0], &p[0], p); printf("%x %p %p\n", p[1], &p[1], p+1); printf("%x %p %p\n", p[2], &p[2], p+2); printf("%x %p %p\n", p[3], &p[3], p+3);输出如下:
0xbfee6bac 0xbfee6bac 0xbfee6ba8 40 0xbfee6bac 0xbfee6bac 30 0xbfee6bad 0xbfee6bad 20 0xbfee6bae 0xbfee6bae 10 0xbfee6baf 0xbfee6baf
示意图如下:
说明几点:
(1)linux中栈内存地址变量为地址增长方向为向下;
(2)linux中字节序为小端,因为int x的低数据0x40位在最低地址0xbff7cccc 上;
代码片段如下:
int x = 0x10203040; char* p = (char*)&x; int main(void) { printf("%p %p %p\n", &x, p, &p); printf("%x %p %p\n", p[0], &p[0], p); printf("%x %p %p\n", p[1], &p[1], p+1); printf("%x %p %p\n", p[2], &p[2], p+2); printf("%x %p %p\n", p[3], &p[3], p+3); return 0; }输出如下:
0x8049810 0x8049810 0x8049814 40 0x8049810 0x8049810 30 0x8049811 0x8049811 20 0x8049812 0x8049812 10 0x8049813 0x8049813示意图如下:
说明几点:
(1)linux中栈内存地址变量为地址增长方向为向上;
(2)linux中字节序为小端,因为int x的低数据0x40位在最低地址0x9049810上;
(3)其实堆的地址增长方向也为向上;
(1)对于有符号数的移位称为算术移动,无符号数的移位成为逻辑移动;
(2)无论是有符号数还是无符号数,逻辑左移和算术左移的规则是一样的:符号位(最高位)由次高位补位,最低位依次补0;
代码片段如下:
int x = 0x7FFFFFFF; cout << hex << x << endl; cout << dec << x << endl; x <<= 1; cout << hex << x << endl; cout << dec << x << endl;
输出如下:
7fffffff 2147483647 fffffffe -2说明几点
(1)有符号正数左移,验证该代码可得:初始值时x为最大的正数7fffffff,即十进制2147483647;x向左移1位后,x变为0xfffffffe(补码表示),变为负数-2;
代码片段如下:
int x = 0x80000001; cout << hex << x << endl; cout << dec << x << endl; x <<= 1; cout << hex << x << endl; cout << dec << x << endl;输出如下:
80000001 -2147483647 2 2
说明几点
(1)有符号负数左移,验证该代码可得:初始值时x为负数0x80000001(补码表示),即十进制-2147483647;x向左移1位后,x变为0x2,十进制2;代码片段如下:
int x = 0x80000000; cout << hex << x << endl; cout << dec << x << endl; x >>= 1; cout << hex << x << endl; cout << dec << x << endl; x >>= 1; cout << hex << x << endl; cout << dec << x << endl;输出如下:
80000000 -2147483648 c0000000 -1073741824 e0000000 -536870912说明几点:
(1)有符号负数右移,验证该代码可得:初始值时x为负数(0x80000000),即十进制-2147483648;x向右移1位后,x变为0xc0000000,十进制-1073741824;x继续向右移1位后,x变为e0000000,十进制-536870912;
代码片段如下:
unsigned int x = 0x80000000; cout << hex << x << endl; cout << dec << x << endl; x >>= 1; cout << hex << x << endl; cout << dec << x << endl; x >>= 1; cout << hex << x << endl; cout << dec << x << endl;输出如下:
80000000 2147483648 40000000 1073741824 20000000 536870912
说明几点:
(1)无符号负数右移,验证该代码可得:初始值时x为无符号数(0x80000000),即十进制2147483648;x向右移1位后,x变为40000000,十进制1073741824;x继续向右移1位后,x变为20000000,十进制536870912;
代码片段如下:
int a = 0x7fffffff; int b = 1; unsigned int c = a + b; //内存中二进制位的表示 int d = a + b; cout << hex << a << " " << b << " " << c << " " << d << endl; cout << dec << a << " " << b << " " << c << " " << d << endl;输出如下:
7fffffff 1 80000000 80000000 2147483647 1 2147483648 -2147483648
说明几点:
(1)正上溢:a和b均为有符号正数,采用补码运算法则得到a+b=0x80000000,c,d和的指只是对内存中的二进制位的解释,c为无符号数,为2147483648;而d为有无符号数,为-2147483648;
代码片段如下:
int a = 0x80000000; int b = -1; unsigned int c = a + b; //内存中二进制位的表示 int d = a + b; cout << hex << a << " " << b << " " << c << " " << d << endl; cout << dec << a << " " << b << " " << c << " " << d << endl;输出如下:
80000000 ffffffff 7fffffff 7fffffff -2147483648 -1 2147483647 2147483647
说明几点:
(1)负上溢:a和b均为负数,采用补码的运算规则为0x80000000+0xffffffff=0x7fffffff;c和d对0x7ffffff的解释是相同的,均为十进制2147483647;
代码片段如下:
short x = 0xff90; //十进制的-112 cout << "x: " << hex << x << " " << dec << x << endl; unsigned short a = x; //相同二进制位的不同解释 cout << "a: "<< hex << a << " " << dec << a << endl; int b = x; //符号位扩展,补1 cout << "b: "<< hex << b << " " << dec << b << endl; unsigned int c = x; //x先转换成int,int转换成unsigned int cout << "c: "<< hex << c << " " << dec << c << endl; int d = a; //a为无符号数,还是补0 cout << "d: "<< hex << d << " " << dec << d << endl; unsigned int e = a; //a为无符号数,还是补0 cout << "e: "<< hex << e << " " << dec << e << endl;输出如下:
x: ff90 -112 a: ff90 65424 b: ffffff90 -112 c: ffffff90 4294967184 d: ff90 65424 e: ff90 65424
说明几点:
(1)处理同样字长的符号数和无符号数的转换,位级的解释模式是不变的;如a=x;
(2)unsigned int c = x; x先转换成int,然后由int转换成unsigned int;并不是x先转换成unsigned short然后进行符号位扩展;
(3)对于a扩展成d和e;由于a是无符号数,因此仅仅是扩展零扩展;仅仅是在有符号数扩展时才会符号扩展(正数补0,负数补1);
代码片段如下:
int x = 0xfffda218; //-155112 cout << hex << x << " " << dec << x << endl; short a = x; //不管符号位,对截断后的二进制位的解释 cout << hex << a << " " << dec << a << endl; unsigned short b = x; //不管符号位,对截断后的二进制位的解释 cout << hex << b << " " << dec << b << endl; int c = a; //有可能精度丢失,此时是根据a的符号位进行符号位扩展的 cout << hex << c << " " << dec << c << endl;输出如下:
fffda218 -155112 a218 -24040 a218 41496 ffffa218 -24040
说明几点:
(1)截断数字仅仅是对截断后的位级模式进行新的解释;
(2) c = a;是根据a的符号位进行符号位扩展的;
标签:
原文地址:http://blog.csdn.net/skyuppour/article/details/44859233