码迷,mamicode.com
首页 > 其他好文 > 详细

【信息表示】数值

时间:2015-04-03 22:31:00      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:

    本节研究信息表示中关于数值的相关问题;


字节序和地址增长方向

栈中变量

代码片段如下:

  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

(3)有符号数, 算术右移时:符号位(正数补0,负数补1)会依次高位补位;无符号数,逻辑右移时,高位补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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!