Chinaunix首页 | 论坛 | 博客
  • 博客访问: 317746
  • 博文数量: 57
  • 博客积分: 146
  • 博客等级: 入伍新兵
  • 技术积分: 769
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-29 14:57
文章分类
文章存档

2014年(39)

2013年(13)

2012年(5)

我的朋友

分类: C/C++

2014-06-26 14:25:25

OS;32bit ubuntu

整型转换的规则:

1.整形提升
若变量的原型都能用int描述的话,其值范围小于INT_MAX的话就转换有符号int,其值范围大于INT_MAX的话就转换成无符号int。

点击(此处)折叠或打开

  1. char c1, c2;
  2. c1 = c1 + c2
整型提升要求每个变量都提升为int大小。两个int相加并把和截断符合于char类型。

点击(此处)折叠或打开

  1. char cresult, c1, c2, c3
  2. c1 = 100;
  3. c2 = 157;
  4. c3 = c1 + c2;
c1+c2=190,超出singed char的最大范围127.由于整型提升,c1,c2都转换为整型进行运算赋值给C3,由于超过char的范围,数据被截断,C3的值为1.

2.每一个整型类型都有一个整型转换优先级,根据优先级决定如何执行转换。C99定义整型转换优先级:
    a.规定char 、short 、int 、long 、long long 的转换级别(Integer Conversion Rank)一个比一个高.
    b.同一类型的有符号和无符号数具有相同的Rank。
    c.标准定义的整型类型的rank高于任何同大小的扩展整型类型的rank。

3.Usual Arithmetic Conversion(操作数类型不同时)
两个算术类型的操作数做算术运算,比如a + b ,如果两边操作数的类型不同,编译器会自动做类型转换,使两边类型相同之后才做运算,这称为Usual Arithmetic Conversion。
    a.如果两边都是有符号数,或者都是无符号数,那么较低Rank的类型转换成较高Rank的类型。例如unsigned int 和unsigned long 做算术运算时都转成unsigned long 。
    b.如果一边是无符号数另一边是有符号数,无符号数的Rank不低于有符号数的Rank,则把有符号数转成另一边的无符号类型。例如unsigned long 和int 做算术运算时都转成unsigned long ,unsigned long 和long 做算术运算时也都转成unsigned long。
  c.一边有符号另一边无符号,并且无符号数的Rank低于有符号数的Rank。这时又分为两种情况,如果这个有符号数类型能够覆盖这个无符号数类型的取值范围,则把无符号数转成另一边的有符号类型。否则,也就是这个有符号数类型不足以覆盖这个无符号数类型的取值范围,则把两边都转成有符号数的Rank对应的无符号类型。
代码:

点击(此处)折叠或打开

  1. int i = -1;
  2. if (i < (unsigned char)1){
  3.     printf("integer promotion\n");
  4. }
unsigned char的rank低于int,且int能覆盖unsigned char范围,所以(unsigned char)1转换为有符号类型,打印出"integer promotion".
代码:

点击(此处)折叠或打开

  1. int i = -1;

  2. if (i < (unsigned int)1){

  3.     printf("integer promotion\n");

  4. }
unsigned int的rank与int的rank,-1转换为无符号类型,条件判断为假。

4.验证整型值的范围
if MAX < result                 return MAX
if MIN <= result <= MAX  return result
if result < MIN                  return MIN


5.确保枚举常量映射到唯一的值
在C中枚举类型映射为整型,枚举变量中成员的值都不是不一样的。

错误:

点击(此处)折叠或打开

  1. enum {red=4, orange, yellow, green, blue, indigo=6, violet}

6.位移:
错误代码:

点击(此处)折叠或打开

  1. int stringify;
  2. char buf[sizeof("256")];
  3. sprintf(buf, "%u", stringify >> 24)
若stringify等于0x80000000, stringify >> 24后等于0xFFFFFF80 ,buf就会溢出。

正确:

点击(此处)折叠或打开

  1. int stringify;
  2. char buf[sizeof("256")];
  3. sprintf(buf, "%u", ((number >> 24) & 0xff))

7.比较分配到更大的整数之前上溯整数大小
错误

点击(此处)折叠或打开

  1. unsigned long long max = UINT_MAX;
  2. void *AllocateBlock(size_t length) {
  3. struct memBlock *mBlock;
  4. if (length + BLOCK_HEADER_SIZE > max) return NULL;
  5. mBlock = malloc(length + BLOCK_HEADER_SIZE);
  6. if (!mBlock) return NULL;
  7. /* fill in block header and return data portion */
  8. return mBlock;
  9. }
length为size_t(unsigned int),length+BLOCK_HEADER_SIZE后其值还是unsigned int范围,导致length+BLOCK_HEADER_SIZE永远为FALSE。
正确代码:

点击(此处)折叠或打开

  1. void *AllocateBlock(size_t length) {
  2. struct memBlock *mBlock;
  3. if ((unsigned long long)length + BLOCK_HEADER_SIZE > max) return NULL;
  4. mBlock = malloc(length + BLOCK_HEADER_SIZE);
  5. if (!mBlock) return NULL;
  6. /* fill in block header and return data portion */
  7. return mBlock;
  8. }
(unsigned long long)length,length转换为更大整数的大小。

错误代码:

点击(此处)折叠或打开

  1. void* AllocBlocks(size_t cBlocks) {
  2. if (cBlocks == 0) return NULL;
  3. unsigned long long alloc = cBlocks * 16;
  4. return (alloc < UINT_MAX) ? malloc(cBlocks * 16) : NULL;
  5. }
cBlocks为size_t,cBlocks*16的结果还是32位,导致alloc
正确:

点击(此处)折叠或打开

  1. void* AllocBlocks(size_t cBlocks) {
  2. if (cBlocks == 0) return NULL;
  3. unsigned long long alloc = (unsigned long long)cBlocks * 16;
  4. return (alloc < UINT_MAX) ? malloc(cBlocks * 16) : NULL;
  5. }

























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