OS;32bit ubuntu
整型转换的规则:
1.整形提升
若变量的原型都能用int描述的话,其值范围小于INT_MAX的话就转换有符号int,其值范围大于INT_MAX的话就转换成无符号int。
-
char c1, c2;
-
c1 = c1 + c2
整型提升要求每个变量都提升为int大小。两个int相加并把和截断符合于char类型。
-
char cresult, c1, c2, c3
-
c1 = 100;
-
c2 = 157;
-
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对应的无符号类型。
代码:
-
int i = -1;
-
if (i < (unsigned char)1){
-
printf("integer promotion\n");
-
}
unsigned char的rank低于int,且int能覆盖unsigned char范围,所以(unsigned char)1转换为有符号类型,打印出"integer promotion".
代码:
-
int i = -1;
-
-
if (i < (unsigned int)1){
-
-
printf("integer promotion\n");
-
-
}
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中枚举类型映射为整型,枚举变量中成员的值都不是不一样的。
错误:
-
enum {red=4, orange, yellow, green, blue, indigo=6, violet}
6.位移:
错误代码:
-
int stringify;
-
char buf[sizeof("256")];
-
sprintf(buf, "%u", stringify >> 24)
若stringify等于0x80000000, stringify >> 24后等于0xFFFFFF80 ,buf就会溢出。
正确:
-
int stringify;
-
char buf[sizeof("256")];
-
sprintf(buf, "%u", ((number >> 24) & 0xff))
7.
比较或分配到更大的整数之前上溯整数大小
错误
-
unsigned long long max = UINT_MAX;
-
void *AllocateBlock(size_t length) {
-
struct memBlock *mBlock;
-
if (length + BLOCK_HEADER_SIZE > max) return NULL;
-
mBlock = malloc(length + BLOCK_HEADER_SIZE);
-
if (!mBlock) return NULL;
-
/* fill in block header and return data portion */
-
return mBlock;
-
}
length为size_t(unsigned int),length+BLOCK_HEADER_SIZE后其值还是unsigned int范围,导致length+BLOCK_HEADER_SIZE永远为FALSE。
正确代码:
-
void *AllocateBlock(size_t length) {
-
struct memBlock *mBlock;
-
if ((unsigned long long)length + BLOCK_HEADER_SIZE > max) return NULL;
-
mBlock = malloc(length + BLOCK_HEADER_SIZE);
-
if (!mBlock) return NULL;
-
/* fill in block header and return data portion */
-
return mBlock;
-
}
(unsigned long long)length,length转换为更大整数的大小。
错误代码:
-
void* AllocBlocks(size_t cBlocks) {
-
if (cBlocks == 0) return NULL;
-
unsigned long long alloc = cBlocks * 16;
-
return (alloc < UINT_MAX) ? malloc(cBlocks * 16) : NULL;
-
}
cBlocks为size_t,cBlocks*16的结果还是32位,导致alloc
正确:
-
void* AllocBlocks(size_t cBlocks) {
-
if (cBlocks == 0) return NULL;
-
unsigned long long alloc = (unsigned long long)cBlocks * 16;
-
return (alloc < UINT_MAX) ? malloc(cBlocks * 16) : NULL;
-
}
阅读(746) | 评论(0) | 转发(0) |