Integral Promotions整数提升和符号扩展(char,unsigned char,signed char)
以下来自msdn:
Objects of an integral type can be converted to another wider integral type (that is, a type that can represent a larger set of values). This widening type of conversion is called "integral promotion." With integral promotion, you can use the following in an expression wherever another integral type can be used:
Objects, literals, and constants of type char and short int
Enumeration types
int bit fields
Enumerators
C++ promotions are "value-preserving." That is, the value after the promotion is guaranteed to be the same as the value before the promotion. In value-preserving promotions, objects of shorter integral types (such as bit fields or objects of type char) are promoted to type int if int can represent the full range of the original type. If intcannot represent the full range of values, then the object is promoted to type unsigned int. Although this strategy is the same as that used by ANSI C, value-preserving conversions do not preserve the "signedness" of the object.
Value-preserving promotions and promotions that preserve signedness normally produce the same results. However, they can produce different results if the promoted object is one of the following:
An operand of /, %, /=, %=, <, <=, >, or >=
These operators rely on sign for determining the result. Therefore, value-preserving and sign-preserving promotions produce different results when applied to these operands.
The left operand of >> or >>=
These operators treat signed and unsigned quantities differently when performing a shift operation. For signed quantities, shifting a quantity right causes the sign bit to be propagated into the vacated bit positions. For unsigned quantities, the vacated bit positions are zero-filled.
An argument to an overloaded function or operand of an overloaded operator that depends on the signedness of the type of that operand for argument matching. (See Overloaded Operators for more about defining overloaded operators.)
整型的对象可以转换为另一个宽整型 (即可可以表示较大设置值的类型。) 转换的此扩大类型称为 “整数提升”。整数提升,在表达式中使用下面,实际上可以使用另一个整数类型:
对象、类型 char 和 short int文本和常数
枚举类型
int 位域
枚举数
C++ 提升 “值保留”。即提升后的值一定相同的值在升级之前。 在值保留的提升,较短整型对象 (如位域或对象类型 char) 提升键入 int ,如果 int 可以表示所有基元类型。 如果 int 不能表示全面值,则对象提升键入 unsigned int。 尽管此方案将与 ANSI C 中使用时,值将转换不想保留 “signedness”对象。
值保留通常保留 signedness 将产生相同的结果的提升和提升。 但是,因此,如果提升的对象是下列值之一,它们可能产生不同的结果:
/、 %、 /=、 %=、 AMP_LT、 AMP_LT=、 AMP_GT或 AMP_GT=操作数
这些运算符决定的结果符号。 因此,值保留和符号保留提升产生不同的结果,在对这些操作数。
AMP_GTAMP_GT 或 AMP_GTAMP_GT=左操作数
,在执行移位操作时,这些运算符将不同的有符号和无符号数。 为签名的数量,转换的权限导致符号位传播到操作空出的数位位置。 对于未签名的数目,则操作空出的数位位置是零填充。
对于依赖于该操作数的类型 signedness 参数匹配的重载运算符的重载函数或操作数的参数。 (有关更多 重载运算符 参见有关定义重载运算符。)
http://msdn.microsoft.com/en-us/library/fc9te331.aspx
K&R C中关于整型提升(integral promotion)的定义为:
"A character, a short integer, or an integer bit-field, all either signed or not, or an object of enumeration type, may be used in an expression wherever an integer maybe used. If an int can represent all the values of the original type, then the value is converted to int; otherwise the value is converted to unsigned int. This process is called integral promotion."
上面的定义归纳下来就是以下两个原则:
1). 只要一个表达式中用到了整型值,那么类型为char、short int活整型位域(这几者带符号或无符号均可)的变量,以及枚举类型的对象,都可以被放在这个整型变量的位置。
2). 如果1)中的变量的原始类型值域可以被int表示,那么原值被转换为int;否则的话,转为unsigned int。
以上两者作为一个整体,被成为整型提升(Integral promotion)
整型提升的概念容易与普通算术类型转换产生混淆。这两者的区别之一在于后者是在操作数之间类型不一致的情况下发生,最终将操作数转换为同一类型。而在算术运算这种情景下,即使操作数具有相同的类型,仍有可能发生整型提升。
例如:
c=a + b;
在上述过程中,尽管两个运算符"+"和"="的操作数全为char型,但在中间计算过程中存在着整数提升:对于表达式a+b ,a、b都是char型,因此被提升至int型后,执行“+”运算,计算结果(int型)再赋值给c(char型),又执行了隐式的类型转换。
是不是有一种很不相信的感觉?Me too,然而标准就是标准。可以使用下面的代码证明上面所描述的过程。
printf ( " the size of the result of a+b :%d " ,sizeof( a+b) );
输出4. 因为a+b转成了int型。
最后提一句,ANSI C规定,编译器如果能保证保证运算结果一致,也可以省略类型提升的操作——这通常出现在表达式中存在常量操作数的时候。
-------------------------------
类型提升
每天都会看CU的博客,尤其是CU首页上面的博客。个人感觉有很多同学并不关注基础知识,
下面的程序输出什么:
signed char a=0xff;
int b=a;
printf("%08X",b);
输出:FFFFFFFF。
我用printf("%d%d",a,b); 输出-1,-1;
改为:
unsigned char a=0xff;
int b=a;
printf("%08X",b);
输出:
000000FF。
我用printf("%d%d",a,b);都输出255.
结果为什么不同。
这就是有关类型提升了。
还有一个例子。
char a=0xff;
signed int b=a;
unsigned int c=b;
printf("%d\n",a);
printf("%d\n",b);
printf("%u\n",c);
b是有符号,c是无符号。
输出:
-1
-1
4294967295 (FFFFFFFF)
请按任意键继续. .
b和c都是int,里面存储的都是FFFFFFFF,只不过解释不一样。b把它解释为负数,c把它解释为整数。
如果你用%d打印C,结果为-1,和b相等。
p=(unsigned char *)a;
p1=(char *)a;
符号扩展和截断的几点认识:
- 1. 符号扩展。。
|
short int a = -4; short int b = 8; print_binary(a); print_binary(b); unsigned short int c = a; //类型转换 unsigned int d = a; print_binary(c); print_binary(d); return 0; |
-4补码1111111111111100.
结果是:
|
11111111 11111100 00000000 00001000 11111111 11111100 11111111 11111111 11111111 11111100 请按任意键继续. . .
|
从结果可以看到:
1.类型转换时不改变位的标志的。
- ……
2.截断处理:
|
int a = -4; short int b = a; int c = 4; short int d = c; print_binary(a); print_binary(b); print_binary(c); print_binary(d) 结果是:
|
发现了,截断高位,不管符号,都要截断高位的部分。
3.乘法和除法:
当存储数据的位数不足以存储乘积的时候,会造成截断误差,通过截断,得到我们的结果不是想要的结果:看下例:
|
char a = 120; print_binary(a); char c = 120; print_binary(c); char d = a * c; cout << (short)d << endl; print_binary(d); int e = a * c; cout << e << endl; print_binary(e); return 0; |
结果是:
|
01111000 01111000 64 01000000 14400 00000000 00000000 00111000 01000000 请按任意键继续. . . |
看到了没有,对于一个char类型的数据,如果将两者的乘积还是保存为char,那么就有可能发生截断,产生误差。此例即为说明,而如果将结果用int来保存,可以看到完整的位表示,然后具体的截断也知道了。此时就可以得到正常的结果,因为有足够的位,没有造成损失。。
转自:http://www.cppblog.com/deercoder/articles/98080.html
------------------------------------------------------
C语言中,当不同类型的数据进行运算的时候,就会发生强制或隐式类型转换,通常是低精度的数据类型扩展到高精度的。有些时候,低精度的位数比较少,扩展到高精度的时候,就要在前面补充一些位。那么这些位是补0还是补1呢?这就涉及到无符号扩展和带符号扩展。
扩展的原则是:1.有符号的数据类型,在向高精度扩展时,总是带符号扩展
2.无符号的数据类型,在向高精度扩展时,总是无符号扩展
怎么理解呢?首先来看一道题目,按此题目讲解完你就明白了!
char ca=128;
unsigned char ucb=128;
unsigned short usc=0;
1)usc=ca + ucb;
printf("%x",usc);
2)usc=ca +(unsigned short)ucb;
printf("%x",usc);
3)usc=(unsignedchar)ca + ucb;
printf("%x",usc);
4)usc=ca+(char)ucb;
printf("%x",usc);
问,在1、2、3、4这4种情况下分别输出什么?
分析:
1)对于char类型,有符号,128已经溢出了,其二进制是 1000 0000,第一位会被当成符号位,也是就是说此时它是负数了,它扩展成unsigned short时,带符号位扩展,符号位为1,所以在前方补1,结果是 1111 1111 1000 000。 ucb类型为nsigned char,无符号,二进制是1000 0000,扩展成unsigned shor,无符号扩展,所以补0,结果是0000 0000 1000 0000,。相加结果为 1 0000 0000 0000 0000 由于unsigned short是二字节,舍弃最前面的1,所以得到0x0,
2)情况和1一样,只是将ucb显示强制转换为unsigned short,所以得到0x0,
3)ca先强制转换为unsignedchar,仍然是1000 0000,注意此时转换后已经是一个无符号数,所以再往unsigned short 扩展时,为无符号扩展,结果为0000 0000 1000 0000,ucb扩展后
也是0000 0000 1000 0000,相加结果为 0000 0001 0000 0000,所以结果为0x100
4)ca转为unsigned short,带符号扩展,为1111 1111 1000 000,ucb先强制转换为char,然后再转为unsigned short,此时也要带符号扩展,所以也是1111 1111 1000 000,两数相加,得到 1 1111 1111 0000 0000 ,所以结果为0xff00
Integral Promotions整数提升和符号扩展(char,unsigned char,signed char)的更多相关文章
- Java的符号扩展与零扩展
byte b = -127; System.out.println(b); // -127 int b1 = b & 0xff; System.out.println(b1); // 129 ...
- char、signed char 和 unsigned char 的区别
ANSI C 提供了3种字符类型,分别是char.signed char.unsigned char.而不是像short.int一样只有两种(int默认就是signed int). 三者都占1个字节( ...
- char、signed char、unsigned char的区别总结。
转载地址:http://hi.baidu.com/thewillreigns/blog/item/67e665c4296e69c038db492d.html char 和 unsigned char是 ...
- char , unsigned char 和 signed char 区别
ANSI C 提供了3种字符类型,分别是char.signed char.unsigned char.char相当于signed char或者unsigned char,但是这取决于编译器!这三种字符 ...
- char, signed char, and unsigned char in C++
关于这三者的区别stackoverrflow里有一个答案是这样说的: 3.9.1 Fundamental types [basic.fundamental] 1 Objects declared as ...
- C 中 char、signed char 和 unsigned char 的区别
C 中 char.signed char 和 unsigned char 的区别 来源:http://bbs.chinaunix.net/thread-889260-1-1.html 参考:https ...
- C语言 1字节signed char的范围为什么是-128~127?
参考 1. 关于 -128 ,+128,-0,+0,-1 的反码补码 | 博客园 2. 八位二进制数为什么表示范围(-128~~+127)理解 | 博客园 无符号单字节范围 无符号单字节unsigne ...
- char 、signed char、unsigned char
看如下代码: char c = -1; signed char sc = -1; unsigned char uc = -1; printf("c=%d, sc=%d, uc=%d, cx= ...
- char和signed char不同编译器下的使用反思
遇到一个问题,在使用一个算法的时候出现了仿真正常,但是在使用时出现函数的返回数据只有正值的异常. 在定位算法问题的时候,由算法函数最后的返回值由后向前推,最后发现问题在与char类型的值在不同编译器下 ...
随机推荐
- 一幅图的知识科普--Google免费DNS服务器
学习源于问题的解决 前段时间在虚拟机上安装了一个oracle软件,虚拟机和宿主机器的网络连接方式是桥接模式的,手动设置了静态ip地址,网关地址,但是发现虚拟机的浏览器不能用. 于是通过ping测试了一 ...
- Regex阅读笔记(五)java操作篇
首先一个demo程序 Java的正则表达式包为java.util.regex,主要是使用其中的Pattern和Matcher. groupCount方法时候都可调用,而大多数方法都必须在匹配尝试成功之 ...
- eval以及json
参考 http://www.cnblogs.com/artwl/archive/2011/09/07/2169680.html http://www.cnblogs.com/objectorl/arc ...
- Sqlite出现SQL error: database disk image is malformed的处理
SQLite有一个很严重的缺点就是不提供Repair命令.导致死亡提示database disk image is malformed它的产生有很多种可能,比如,磁盘空间不足,还有就是写入数据过程中突 ...
- VPN各种方案
http://www.maimiaovpn.com 大家都是用什么方法FQ的?我原来用的XskyWalker浏览器 但我用的电信网现在不行了.大家用的什么方法可否告诉我一下我用yes-vpn,10元一 ...
- MFC基础,MFC自绘控件学习总结.---转
前言:从这学期开始就一直在学习自绘控件(mfc),目标是做出一款播放器界面,主要是为了打好基础,因为我基础实在是很烂....说说我自己心得体会以及自绘控件的方法吧,算是吐槽吧,说的不对和不全的地方,或 ...
- CSS实现背景图尺寸不随浏览器大小而变化的两种方法
一些网站的首页背景图尺寸不随浏览器缩放而变化,本例使用CSS 实现背景图尺寸不随浏览器缩放而变化,方法一. 把图片作为background,方法二使用img标签.喜欢的朋友可以看看 一些网站的首页 ...
- Oracle笔记之对象权限与系统权限总结
对象权限与系统权限 创建表和创建session是系统权限: 系统管理员是有权限去訪问其它表的 以sys登录 sqlplus sys/on_change_install as sysdba; 创 ...
- C语言中操作符的优先级大全
C语言中操作符的优先级大全, 当然c++, Objective-C,大部分语言都试用. 下面是来自The C Programming Language 2th的总结. OperatorsAssocia ...
- B. Friends and Presents(Codeforces Round #275(div2)
B. Friends and Presents time limit per test 1 second memory limit per test 256 megabytes input stand ...