编写安全代码:再论整数类型转换 (
2012-12-07 10:18
459 查看
编写安全代码:再论整数类型转换 (2011-10-11 11:16)
标签: 安全 整数 类型转换
分类: 编写安全无错代码
本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
作者:gfree.wind@gmail.com
博客:linuxfocus.blog.chinaunix.net
前几天看C99标准,写了两篇关于整数提升的博文,http://blog.chinaunix.net/space.php?uid=23629988&do=blog&id=2938697在这篇的评论中,pragma朋友提出了一个问题。经过了重新阅读C99,和别人讨论,外加思考,得到了答案。这再次加深了我对整数提升的理解,所以需要进一步总结一下这个问题。
先看看pragma提出的问题吧。
#include <stdlib.h>
#include <stdio.h>
#define PRINT_COMPARE_RESULT(a, b) \
if (a > b) { \
printf( #a " > " #b "\n"); \
} \
else if (a < b) { \
printf( #a " < " #b "\n"); \
} \
else { \
printf( #a " = " #b "\n" ); \
}
int main()
{
signed int a = -1;
unsigned int b = 2;
signed short c = -1;
unsigned short d = 2;
PRINT_COMPARE_RESULT(a,b);
PRINT_COMPARE_RESULT(c,d);
return 0;
}
输出结果为
[root@Lnx99 test]#./a.out
a > b
c < d
为什么将int换为short后,结果就不一样了呢?
在C99标准中算数运算中有两种conversion,一个是integer promotion,另外一个是usual
arithmetic conversions。在前面的博文中,我研究的是第二种,并将其理解为integer promotion,其实是不准确的。
下面是C99中关于第一种integer promotion的描述:
If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All
other types are unchanged by the integer promotions.
——在C99的上下文,这个integer promotion发生在算术运算的时候。
而C99关于usual arithmetic conversions,参加我这篇博文:http://blog.chinaunix.net/space.php?uid=23629988&do=blog&id=2938697
这样的话,也就是说在算术运算中,会涉及两种integer conversion。上面的测试代码的结果,也是由此而来。
下面开始分析:
对于a和b来说,integer promotion相当于不起作用,所以只进行usual
arithmetic conversion,根据规则,将a转为unsigned int,所以a>b。
对于c和d来说,首先integer promotion会起作用,c和d都会转为int型,也就是说相当于int
c = -1,int d = 2;然后进行usual arithmetic conversion,因为两者此时都为int型,那么自然结果是c < d了。
现在答案已经清晰了,但是却让我感到一阵阵忐忑,因为这样的整数转换规则太容易让人犯错了。对于我们来说,虽然已经比较明晰两个规则,但是在代码中还是要尽量避免有符号数和无符号数的比较。如果无法避免,为了清楚的表明自己的目的,最好使用强制类型转换。
标签: 安全 整数 类型转换
分类: 编写安全无错代码
本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。
作者:gfree.wind@gmail.com
博客:linuxfocus.blog.chinaunix.net
前几天看C99标准,写了两篇关于整数提升的博文,http://blog.chinaunix.net/space.php?uid=23629988&do=blog&id=2938697在这篇的评论中,pragma朋友提出了一个问题。经过了重新阅读C99,和别人讨论,外加思考,得到了答案。这再次加深了我对整数提升的理解,所以需要进一步总结一下这个问题。
先看看pragma提出的问题吧。
#include <stdlib.h>
#include <stdio.h>
#define PRINT_COMPARE_RESULT(a, b) \
if (a > b) { \
printf( #a " > " #b "\n"); \
} \
else if (a < b) { \
printf( #a " < " #b "\n"); \
} \
else { \
printf( #a " = " #b "\n" ); \
}
int main()
{
signed int a = -1;
unsigned int b = 2;
signed short c = -1;
unsigned short d = 2;
PRINT_COMPARE_RESULT(a,b);
PRINT_COMPARE_RESULT(c,d);
return 0;
}
输出结果为
[root@Lnx99 test]#./a.out
a > b
c < d
为什么将int换为short后,结果就不一样了呢?
在C99标准中算数运算中有两种conversion,一个是integer promotion,另外一个是usual
arithmetic conversions。在前面的博文中,我研究的是第二种,并将其理解为integer promotion,其实是不准确的。
下面是C99中关于第一种integer promotion的描述:
If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All
other types are unchanged by the integer promotions.
——在C99的上下文,这个integer promotion发生在算术运算的时候。
而C99关于usual arithmetic conversions,参加我这篇博文:http://blog.chinaunix.net/space.php?uid=23629988&do=blog&id=2938697
这样的话,也就是说在算术运算中,会涉及两种integer conversion。上面的测试代码的结果,也是由此而来。
下面开始分析:
对于a和b来说,integer promotion相当于不起作用,所以只进行usual
arithmetic conversion,根据规则,将a转为unsigned int,所以a>b。
对于c和d来说,首先integer promotion会起作用,c和d都会转为int型,也就是说相当于int
c = -1,int d = 2;然后进行usual arithmetic conversion,因为两者此时都为int型,那么自然结果是c < d了。
现在答案已经清晰了,但是却让我感到一阵阵忐忑,因为这样的整数转换规则太容易让人犯错了。对于我们来说,虽然已经比较明晰两个规则,但是在代码中还是要尽量避免有符号数和无符号数的比较。如果无法避免,为了清楚的表明自己的目的,最好使用强制类型转换。
相关文章推荐
- 编写安全代码:再论整数类型转换
- 编写安全代码:再论整数类型转换
- [编写高质量代码:改善java程序的151个建议]建议65 避开基本类型数组转换列表陷阱
- js整数字符串转换为金额类型数据(示例代码)
- js整数字符串转换为金额类型数据(示例代码)
- ORA-01455: 转换列溢出整数数据类型
- 编写安全代码:数组和指针的本质以及何时不能互换
- 提高你的Java代码质量吧:用整数类型处理货币
- 对Excle的行和列进行检查 单元格类型转换代码 ;
- C#中bool类型不能和其它整数类型转换
- Beginning C# Objects从概念到代码——1.10 隐式类型转换和显式类型转换
- 搬砖中的小事之代码(六)--列表显示的字段与数据库中字段类型不匹配,需要在查询后进行简单转换
- 编写一个函数将一个十六进制数的字符串参数转换成整数返回
- 如何编写异常安全的C++代码
- java主类结构、基本数据类型、 变量与常量、运算符、数据类型转换、代码注释与编码规范
- 如何编写异常安全的C++代码
- 编写安全代码——不要用memcmp比较structure
- 编写一个函数itob(int n,char s[], int b),将整数n转换为以b进制的数。保存到s中。
- C#中数据类型的安全转换(is,as)