Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3785499
  • 博文数量: 880
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 6155
  • 用 户 组: 普通用户
  • 注册时间: 2016-11-11 09:12
个人简介

To be a better coder

文章分类

全部博文(880)

文章存档

2022年(5)

2021年(60)

2020年(175)

2019年(207)

2018年(210)

2017年(142)

2016年(81)

分类: C/C++

2018-10-30 15:51:10

原文地址:“C”中的算数转换 作者:lvyilong316

写在前面:本来因为一个朋友问我为什么可以给unsigned int赋值负数,我打算写一篇关于解释unsigned的文章。但是写的过程中发现有很多地方需要涉及其他的知识点,特别是关于整型提升和算数转换。所以就翻了一下之前看过的书,做了一个总结,感觉自己又学到了不少。由于我不是写教科书,有些用语和描述难免不够准确。另外,由于本人能力有限,有错之处在所难免,希望各位看到此文的朋友如果发现有什么错误请留言指正,或发邮件交流。

(电子邮箱:                  ——转载请注明出处,lvyilong316 

2. 算数转换

2.1 什么是算数转换

   许多操作数类型为算数类型的双目运算符会引发转化,并以类似的方式产生结果类型。他的目的是产生一个普通类型,同时也是运算结果的类型。这个模式称为“寻常算数转换”。

                                                    ——ANSI C手册

2.2 如何进行转换

    当执行算数运算时,操作数的类型如果不同,就会发生转换。 数据类型一般朝着浮点精度更高、长度更长的方向转换 。整型数如果转换为signed不会丢失信息,就转换为signed,否则就转换为unsigned。 这个称为值保留value preserving)原则,与K&R C所采用的无符号保留unsigned preserving)原则不同。

无符号保留:就是当一个无符号类型与int或更小的整形混合使用时结果类型是无符号类型。(忘了这个吧,我们以ANSI C为准)

值保留:结果可能是有符号数,也可能是无符号数,取决于操作数类型的相对大小。

也许你读了上面的解释还不清楚,那么我来给你解释下:、

    当两个类型长度不同时,短的类型根据自己是signed还是unsigned进行位扩展,然后按较长的类型解释signedunsigned(类似类型提升)。有人会问为什么得到这个结论,因为短类型向长类型扩展肯定不会丢失信息,可以按照unsigned解释,而长类型按什么解释取决于他自身,如果长类型本身为unsigned,那解释为signed肯定要丢失信息,所以以长类型为准解释signed或者unsigned

说明:虽然32位下longint都是4个字节,但是int要向long转(可以当做longint长)。

当两个类型相同,signed类型不同时(比如intunsigned int),按照unsigned解释(即都转为unsigned)。这又是为什么呢?因为两个同为类型相同,unsigned的转为signed肯定要丢失高位信息。

说明:这里不包括charunsigned char,short,unsigned short,因为这些在一起会发生整形提升(扩展后,解释为signed int)。

2.3 什么情况下执行算数转换,什么情况下执行整形提升 

     当有charshort int或者int位段(无论signedunsigned参与的表达式,先对其进行整型提升,提升后若有intsignedunsigned)或long等更长的类型,在按照算数转换进行转换。否则直接进行算数转换。(float类似)

2.4 实例分析

(1) int a = -1;

   unsigned int b = 1;

   printf("%d", a > b);//输出1

分析:算数转换,同类型,都转为unsigned int再来比较。a转化为无符号数后就是0xFFFFFFFF,肯定大于b

(2) char a = -1;

   unsigned char b = 1;

   printf("%d", a > b);//输出0

分析:整形提升,参看上一节分析。

(3) int a = -1;

   unsigned char b = -1;

   printf("%d\n", a < b);//输出是1

分析:类型提升,b扩展为0x000000FF,解释为int255当然大于-1

(4) char a = -1;

   unsigned int b = -1;

   printf("%d\n", a == b);//输出1

分析:整形提升+算数转换,首先a0xFF,按照signed扩展为0xFFFFFFFF,解释为int,之后intunsigned int比较算数转换为unsigned int解释。ab都为0xFFFFFFFF对应的无符号int,所以相等。其实将b改为int类型,输出一样为1,以为这时只发生了整形提升,提升后两个0FFFFFFFF都解释为int类型(-1,所以相等。b改为unsigned long long呢?还是输出1,先发生整形提升,a提升为int,在算数转换——aint扩张为8字节,并解释成unsigned long long0XFFFFFFFFFFFFFFFF),和b相同。

 

下面是来自网上的一个总结,其实经过这两节的讨论,基本不需要这样去记了,我们可以简单的概括为:有小整形的先提升,signed不同则转换。

无符号int与有符号int比较大小,转化为无符号int来比较

int类型与非无符号int的类型比较时,非无符号int的类型转化为int来比较

无符号int类型与其他类型如unsigned shortsigned shortunsigned char, char 比较时,其他类型一律转化为无符号int类型来比较

非无符号int类型和非int类型如unsigned shortsigned shortunsigned char, char 比较时,一律转化为int类型来比较

 

阅读(1541) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~