从unsigned 复习数据类型

本文深入探讨了一个C++面试题:unsigned int i = 3; cout << i * -1; 结果为何是4294967293。通过解释不同数据类型之间的转换规则,特别是混合使用unsigned int与int类型时的行为,揭示了这一现象背后的原理。同时,文章还总结了数据类型表示范围、隐式类型转换规则以及定点浮点表示范围等关键概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

-------转:

这样一个题,据说是微软面试题:

unsigned int i=3;
cout<<i * -1;
问结果是多少。
 
第一反应:-3。不过结果似乎不是这样的,写了个程序,运行了一下,发现是:4294967293。很诡异的一个数字,怎么也想不明白为什么会是这么个奇怪的数字。但是在我发现这数的十六进制数是FFFFFFFD时,我想我已经离答案很近了...
 
这个涉及到了混合着不同数据类型的表达式中的数据类型的转换问题。在总结转换问题之前,先说明一下各种数据类型(只说明numeric类型的),下表来自MSDN:
Type NameBytesOther NamesRange of Values
int*signed,
signed int
System dependent
unsigned int*unsignedSystem dependent
    
char1signed char–128 to 127
unsigned char1none0 to 255
short2short int,
signed short int
–32,768 to 32,767
unsigned short2unsigned short int0 to 65,535
long4long int,
signed long int
–2,147,483,648 to 2,147,483,647
unsigned long4unsigned long int0 to 4,294,967,295
enum*noneSame as int
float4none3.4E +/- 38 (7 digits)
double8none1.7E +/- 308 (15 digits)
long double10none1.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 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值