首先请大家先思考一下3个问题,问题相互之间是有关联的。
1,整型字面值是属于整型家族9种中的哪一种呢?
2,什么是算术转换?如何转换的?
3,什么是整型提升?如何提升的?为什么会有整形提升?
下面解答上述问题。
1,整型字面值是属于整型家族9种中的哪一种呢?
答案取决于字面值时如何书写的。比如在整数字面值后面后面添加字符L或l,可以使这个整数被解释为long整型值,字符U或u则用于把数值制定为unsigned整型值。如果在一个字面值后面各添加这两组字符中的一个,那么它就解释为unsigned long整型值。
整型字面值可能int,long或unsigned long。在缺省情况下,它是最短类型但能完整容纳这个值。
例如:在监视中,我们可以明确的看到编译器对于整型字面值在计算时是如何存储的
可以看出即便是再小的数,也会当做是int型,随着整数的增大,整数的类型也会随着变大。直到超出最大范围。
2,什么是算术转换?如何转换的?
算术转化:如果某个操作符的各个操作数属于不通过的类型,那么除非其中一个操作数转换为另外一个操作数的类型,否则操作就无法进行。
下面的层次体系称为寻常算术转换(usual arithmetic conversion)
long double
double
float
unsigned long int
unsigned int
int
vs文档中常用算术转换规定。
-
如果任一操作数是 long double 类型,则将另一个操作数转换为 long double 类型。
-
如果未满足上述条件,并且任一操作数是 double 类型,则将另一个操作数转换为 double 类型。
-
如果未满足上述两个条件,并且任一操作数是 float 类型,则将另一个操作数转换为 float 类型。
-
如果未满足上述三个条件(所有操作数都不是浮点型),则对操作数执行整型转换,如下所示:
-
如果任一操作数是 unsigned long 类型,则将另一个操作数转换为 unsigned long 类型。
-
如果未满足上述条件,并且任一操作数是 long 类型且另一个操作数是 unsigned int 类型,则将两个操作数都转换为 unsigned long类型。
-
如果未满足上述两个条件,并且任一操作数是 long类型,则将另一个操作数转换为 long 类型。
-
如果未满足上述三个条件,并且任一操作数是 unsigned int类型,则将另一个操作数转换为 unsigned int 类型。
-
如果未满足上述任何条件,则将两个操作数转换为 int 类型。
-
例子:
int a = -1;
unsigned int b = 0xffffffff;
char c = -1;
if (a > b)
printf("a > b\n");
else if (a == b)
printf("a = b\n");
else
printf("a < b\n");
if (c > sizeof(c))
printf("c > sizeof(c)\n");
输出:
解析:
结果并没有按照我们想的大小来比较,而是发生了我们没有看见的隐式算术转换。
int类型a和unsigned int类型b来操作数'<'、'=='、'>'两边,比较时,其中a发生算术转换暂时变为unsigned int a.而-1的补码和0xffffffff的补码相同,所以两数相同。输出a = b;
同理。sizeof()返回值为size_t类型的1, unsigned int。char c会变为unsigned int c,然后与unsigned int 1比较大小,自然是大于1.
3,什么是整型提升?为什么会有整形提升?如何提升的?
概念:C的整型算术运算总是至少以缺省整数类型的精度(int)来进行的。为了获取这个精度,表达式中的字符型和短整型操作数在使用之前被转化为普通整型,这种转化称为整型提升(integral Promotion)。换句话说,在表达式计算时,各种整型首先要提升为int类型,如果int类型不足以表示则要提升为unsigned int类型,然后进行表达式的运算。
存在原因:通常情况下,在32位平台下,在对int类型的数值做运算时,CPU的运算速度是最快的。C语言是一个注重效率的语言,所以它会做整型提升,使得程序运行速度更快。
提升规则:有符号的在左边补上符号位,无符号的在左边补上0。
想要知道有没有整型提升,关键还是要看汇编。
例子:
注意下图中的汇编语句,对比char和int的不同
可以发现,在初始化a,b,aa,bb时,都是用整型字面值赋值。对于a,b来说只是截取了其中一部分。但不影响获得后a,b的内容。
重点:对比 char c = a+b;和int cc = aa+bb;这两行代码的汇编不同;
一个是movsx,一个是mov;
movsx:表示带符号扩展,并传送。
即:在计算c时,a和b进行了符号扩展,b和c的值被提升为普通整型,然后再执行加法运算。加法运算的结果将被截断,然后在存储于c中。
下面给出一个整型提升方面的经典例子。
char c;
unsigned char uc;
unsigned short us;
c = 128;
uc = 128;
us = c + uc;
printf("Ox%x\n", us);
us = (unsigned char)c + uc;
printf("0x%x\n", us);
us = c + (char)uc;
printf("0x%x\n", us);
各位可以试着练练手,画画图。然后与答案对比下。
答案:
注意有无符号数字的存储形式。
如何整型提升的
注:算术变换和整形提升的区别:
算术变换主要针对操作符两边操作数类型不同,用来解决类型不匹配问题。
整型提升主要针对操作数是否便于计算,用来解决计算求值问题。