以下来自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,然而标准就是标准。可以使用下面的代码证明上面所描述的过程。
输出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类型的值在不同编译器下 ...
随机推荐
-
Linux下百度云盘报 获取bdstoken失败
在用linux下百度云盘工具(bcloud),登录时,报获取bdstoken失败. 在网上搜了一下,解决办法如下. 找到auth.py文件 locate auth.py |grep bcloud 结果 ...
-
在Ubuntu上安装Hadoop(单机模式)步骤
1. 安装jdk:sudo apt-get install openjdk-6-jdk 2. 配置ssh:安装ssh:apt-get install openssh-server 为运行hadoop的 ...
-
Codeforces Round #367 (Div. 2) A. Beru-taxi (水题)
Beru-taxi 题目链接: http://codeforces.com/contest/706/problem/A Description Vasiliy lives at point (a, b ...
-
git基本命令--status, add, diff, commit, log
git status: git status命令的输出十分详细,但其用语有些繁琐. 如果你使用 git status -s 命令或 git status --short 命令,你将得到一种更为紧凑的格 ...
-
Python是如何实现生成器的原理
python中函数调用的实质原理: python解释器(即python.exe)其实是用C语言编写的, 在执行python代码时,实际上是在用一个叫做Pyeval_EvalFramEx(C语言的函数) ...
-
【js课设】电子画板01
这学期web开发课的课设选了电子画板课题.(人家本来想做富文本编辑器的嘛然鹅老师在第二版里把这题删掉了。゚ヽ(゚´Д`)ノ゚。) 主要考虑的有[界面美观][画笔类型][画布分层]这三个点了. [界面美 ...
-
Spring Cloud Zipkin
Zipkin the idea is from the googlge paper:Dapper https://yq.aliyun.com/articles/60165 https://www.e4 ...
-
ARMV8 datasheet学习笔记4:AArch64系统级体系结构之编程模型(4)- 其它
1. 前言 2.可配置的指令使能/禁用控制和trap控制 指令使能/禁用 当指令被禁用,则这条指令就会变成未定义 指令Trap控制 控制某条或某些指令在运行时进入陷阱,进入陷阱的指令会产生trap异常 ...
-
Java程序设计17——多线程-Part-B
5 改变线程优先级 每个线程执行都具有一定的优先级,优先级高的线程获得较多的执行机会,而优先级低的线程则获得较少的执行机会. 每个线程默认的优先级都与创建它的父线程具有相同的优先级,在默认情况下,ma ...
-
ARC075 E.Meaningful Mean(树状数组)
题目大意:给定n和k,问an中有多少子区间的平均值大于等于k 很巧妙的一个式子,就是如果一个区间[l, r]满足条件 那么则有 sum[r] - sum[l-1] >= (r-l+1)*k 整理 ...