-------转:
这样一个题,据说是微软面试题:
unsigned int i=3;
cout<<i * -1;
cout<<i * -1;
问结果是多少。
第一反应:-3。不过结果似乎不是这样的,写了个程序,运行了一下,发现是:4294967293。很诡异的一个数字,怎么也想不明白为什么会是这么个奇怪的数字。但是在我发现这数的十六进制数是FFFFFFFD时,我想我已经离答案很近了...
这个涉及到了混合着不同数据类型的表达式中的数据类型的转换问题。在总结转换问题之前,先说明一下各种数据类型(只说明numeric类型的),下表来自MSDN:
Type Name | Bytes | Other Names | Range of Values |
int | * | signed, signed int | System dependent |
unsigned int | * | unsigned | System dependent |
char | 1 | signed char | –128 to 127 |
unsigned char | 1 | none | 0 to 255 |
short | 2 | short int, signed short int | –32,768 to 32,767 |
unsigned short | 2 | unsigned short int | 0 to 65,535 |
long | 4 | long int, signed long int | –2,147,483,648 to 2,147,483,647 |
unsigned long | 4 | unsigned long int | 0 to 4,294,967,295 |
enum | * | none | Same as int |
float | 4 | none | 3.4E +/- 38 (7 digits) |
double | 8 | none | 1.7E +/- 308 (15 digits) |
long double | 10 | none | 1.2E +/- 4932 (19 digits) |
对上表补充说明一下:
1)在32位机上,int型和unsigned int型都是32位的(4个字节)。
2)enum会跟据最大值来决定类型,一般来说为int型,如果超出int型所能表示的范围,则用比int型大的最小类型来表示(unsigned int, long 或者unsigned long)
3)关于类型的大小。一般用所能表示的数据范围来比较类型的大小,如char型<unsigned char型<short型...在表达式中,一般都是由小的类型向大的类型转换(强制类型转换除外)
1、所有比int型小的数据类型(包括char,signed char,unsigned char,short,signed short,unsigned short)转换为int型。如果转换后的数据会超出int型所能表示的范围的话,则转换为unsigned int型;
2、bool型转化为int型时,false转化为0,true转换为1;反过来所有的整数类型转化为bool时,0转化为false,其它非零值都转为true;
3、如果表达式中混有unsigned short和int型时,如果int型数据可以表示所有的unsigned short型的话,则将unsigned short类型的数据转换为int型,否则,unsigned short类型及int型都转换为unsigned int类型。举个例子,在32位机上,int是32位,范围–2,147,483,648 to 2,147,483,647,unsigned short是16位,范围0 to 65,535,这样int型的足够表示unsigned
short类型的数据,因此在混有这两者的运算中,unsigned short类型数据被转换为int型;
5、如果表达式中既有int 又有unsigned int,则所有的int数据都被转化为unsigned int类型。
在表达式i*-1中,i是unsigned int型,-1是int型(常量整数的类型同enum),按第5条可以知道-1必须转换为unsigned int型,即0xffffffff,十进制的4294967295,然后再与i相乘,即4294967295*3,如果不考虑溢出的话,结果是12884901885,十六进制0x2FFFFFFFD,由于unsigned
int只能表示32位,因此结果是0xfffffffd,即4294967293。
/*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
我的总结:
一、注意隐式类型转换
unsigned i =5;
i*
实质为
i*(unsigned)-1;
上式在vc下可以通过编译;
而在vs2008下则会要求显式类型转换;
二、定点浮点表示范围
计算机中的数值都用补码表示 补码计算不需要分离出符号位,而原码不行
原码下:00000001+10000001=10000010 1+(-1)= - 2
补码下:00000001+11111111=00000000 (忽略溢出部分)
关于正负数:
注意:
比如n=1 范围是 -128 ~ 127 而-128 的原码表示 1,1000,0000 (9位 )补码表示是 1,1000,0000 留8位 忽略溢出 得到1000,0000 -128
而 -127 的补码表示 = 0 - (1 111,1111 原) =1 000,0001
三、数据类型表示范围:
假设某数据类型占用n字节,即8 n bit;
有符号整型(书上叫定点整数)
- 2 ^ (8n-1) ~ 2^(8n-1)-1 最高位是符号位 所以8n-1
无符号整型:
0 ~ 2^(8n) - 1 (1111==15)
关于数据类型占位:
根据上表 int 在32位下占四字节 而在16位系统是两字节(或者说由编译器决定的)
不过数据类型占位必须符合
1 sizeof(short int)<=sizeof(int)
2 sizeof(int)<=sizeof(long int)
3 short int至少应为16位(2字节)
4 long int至少应为32位。
有符号浮点型:(浮点表示待续 = =)
无符号浮点型:
三、
(unsigned)-1==0xffffffff ?
注意:
比如n=1 范围是 -128 ~ 127 而-128 的原码表示 1,1000,0000 (9位 )补码表示是 1,1000,0000 留8位 忽略溢出 得到1000,0000 -128
而 -127 的补码表示 = 0 - (1 111,1111 原) =1 000,0001