C中的类型自动提升、printf("%08x",number)

同一句语句或表达式如果使用了多种类型的变量和常量(类型混用),C 会自动把它们转换成同一种类型。以下是自动类型转换的基本规则:

1. 在表达式中,char 和 short 类型的值,无论有符号还是无符号,都会自动转换成 int 或者 unsigned int(如果 short 的大小和 int 一样,unsigned short 的表示范围就大于 int,在这种情况下,unsigned short 被转换成 unsigned int)。因为它们被转换成表示范围更大的类型,故而把这种转换称为“升级(promotion)”。

2. 按照从高到低的顺序给各种数据类型分等级,依次为:long double, double, float, unsigned long long, long long, unsigned long, long, unsigned int 和 int。这里有一个小小的例外,如果 long 和 int 大小相同,则 unsigned int 的等级应位于 long 之上。char 和 short 并没有出现于这个等级列表,是因为它们应该已经被升级成了 int 或者 unsigned int。

3. 在任何涉及两种数据类型的操作中,它们之间等级较低的类型会被转换成等级较高的类型。

4. 在赋值语句中,= 右边的值在赋予 = 左边的变量之前,首先要将右边的值的数据类型转换成左边变量的类型。也就是说,左边变量是什么数据类型,右边的值就要转换成什么数据类型的值。这个过程可 能导致右边的值的类型升级,也可能导致其类型降级(demotion)。所谓“降级”,是指等级较高的类型被转换成等级较低的类型。(左操作数结果溢出另考虑!!!一般此时也应该加强制类型转换!c和指针p80)

 【但不包括指针类型哦】

int main()
{
int a = 99,*e;
char b = ‘b’,c = b;

e = (int *)a;//必须强制类型转换!否则报error
b = a;
a = c;//这2个属于” = “的类型升降级
printf(“b=%c,a=%d\n”,b,a);

}

5. 作为参数传递给函数时,char 和 short 会被转换成 int,float 会被转换成 double。使用函数原型可以避免这种自动升级。

32位机

int 4 -2^31 ~~(2^31-1)

unsigned int 4 0~~(2^32-1)

C/C++/C#/Java语言中默认地写一个小数的数字, 它的类型是double, 不是float, 要想显式地表达它是float, 在数字后附加一个f或F.
C语言中的printf的%f 格式符不是代表 float, 而是代表fixed, 即以定点小数的形式显示, 而printf根本就没有显示一个float的格式符, 对于原型如printf(const char *, …) 这样的函数, 传递一个 float给函数, 也会被先转换成double 进行调用. 这是C语言的类型提升规则.
与printf不对称的是, scanf家族的函数却有一个 %f来输入一个float, 以%lf来输入一个double, 注意不是%d来输入double, 因为printf中已经用了%d来表示一个decimal(十进制)的整数, scanf的设计为了尽量与之对称, 目的是减少程序员的记忆量.
不要以为C/C++语言中的强制类型转换一定不消耗CPU时间, 不对应CPU指令. 检查你的编译器的汇编输出.

程序员面试宝典中关于类型转换的例题:
1 #include
2 using namespace std;
3 int main()
4 {
5 unsigned int a = 0xFFFFFFF7;
6 unsigned char i = (unsigned char)a;
7 char* b = (char*)&a;
8
9 printf(“%08x, %08x\n”, i, *b);
10 }
程序结果输出 :fffffff7,《宝典》中解释为
1 unsigned int* p = &a; // p中的内容是的地址,即p指向a
2 char* b = (char*)p; // 此处的强制转换只是使b也指向a而已
3 // 这里是char类型的指针转换,而不是char类型的转换,影响的只是指针的寻址
《宝典》认为最终b的指向和&a一样,所以程序输出就是&a指向的:fffffff7,这个解释显然是不对的,如果我们把a的值改为0x123456f7,程序也会输出fffffff7,
而按照《宝典》的说法,应该输出123456f7才对。
正确的解释是怎样的呢?
首先我们要有这么一个认识:在X86系列的机器中,数据的存储是“小端存储”,小端存储的意思就是,对于一个跨多个字节的数据,其低位存放在低地址单元,其高位放在高
地址单元。比如一个 int 型的数据ox12345678,假如存放在0x00000000,0x00000001,0x00000002,0x00000003这四个内存单元中,那么ox00000000中放的是
低位的ox78,而ox00000003中放的是高位的0x12,以此类推。
有了以上的认识,我们可以继续分析上面的程序为什么输出fffffff7:
char* b = (char*)&a;这句话到底干了什么事呢?其实说来也简单,&a可以认为是个指向 unsigned int类型数据的指针对吧,(char )&a则把&a强制转换成 char 类型
的指针,并且这个时候发生了截断!截断后,指针b只指向oxf7这个数据(为什么b指向最低位的oxf7而不是最高位的oxff?想想上面刚刚讲过的”小端存储”吧,低地址单元存
放低位数据,),又由于指针b是 char *型的,属于有符号数,所以有符号数0xf7在printf()的作用下输出fffffff7( 这个过程中其实发生了参数类型提升default argument
promotions

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值