格式转换问题
2015-09-01 00:52
225 查看
最近发现了一道比较有趣的题目:
乍一看,问题在于格式转换上,a+b 会先把b int 转成unsigned int,由于(unsigned)-2 = 0x1111 1110 也就是说a+nb不会小于0, 等于零也只有在a = 2,n = 1的情况下,于是程序会有栈溢出的问题存在。
想了想,还是总结一下格式转换的问题:
总的方向是:默认 小范围的往大范围的方式转换,比如
大的往小的,需要格式转换,一般常用格式转换是(new_type) 比如 int a = (int)0.2f
或者是指针读取:
![](http://images.cnitblog.com/blog2015/666950/201503/251542146927447.png)
其实 float => int 又与指针读取有什么区别呢? 不过是在float的地址上用int的指针读取的值(其实小数的存储方式有点特别,详情请看float的存储方式,所以这种想法还是欠妥,以及 在float与int的转换 里面你可以理解为什么判等的时候不常用小数,感兴趣的同学可以执行我下面的程序,会有意外收获,提示: 精度)
这里顺带提一下c++的四种类型转换:
这四种转换的用法一致:如
有点像函数,而里面的<int>,有点像<T>模版
上表参考
其实C++的四种类型转换是普通类型转换的俩种普例+俩种特例,附带某些功能(如去除const,类型检查)。
附:
const测试:
从上方可以看出 对于 const int *p 不能直接修改*p, 只能通过指向的num1(非const)修改 或者从const_cast得到指针cp,修改*cp。也就是*p 只读,而p可读写。(一个烂例子:你可以选择不同地方住,但是住下来了,内容是不能变动的)
对于int * const p 不能修改p的指向(*p的地址、p变量的内容),但是可以修改*p的内容,虽然不能跟换p的指向(另一个烂例子:你住的地方不好更改,但是你可以布置一下家居)
[code]void fun() { unsigned int a = 2013; int b = -2; int c = 0; while (a + b > 0) { a = a + b; c++; } printf("%d", c); } 问:最后程序输出是多少?
乍一看,问题在于格式转换上,a+b 会先把b int 转成unsigned int,由于(unsigned)-2 = 0x1111 1110 也就是说a+nb不会小于0, 等于零也只有在a = 2,n = 1的情况下,于是程序会有栈溢出的问题存在。
想了想,还是总结一下格式转换的问题:
总的方向是:默认 小范围的往大范围的方式转换,比如
[code]int+double = double, unsigned int + int = unsigned int
大的往小的,需要格式转换,一般常用格式转换是(new_type) 比如 int a = (int)0.2f
或者是指针读取:
[code]struct IP{ byte verson_hlen; byte service_type; short len; …… }; void decode(char *ipData) { IP *p_ip = (IP*)ipData; printf("head length: %2d, total length: %d\n", p_ip->verson_hlen & 0x01 * 4, len); }
![](http://images.cnitblog.com/blog2015/666950/201503/251542146927447.png)
其实 float => int 又与指针读取有什么区别呢? 不过是在float的地址上用int的指针读取的值(其实小数的存储方式有点特别,详情请看float的存储方式,所以这种想法还是欠妥,以及 在float与int的转换 里面你可以理解为什么判等的时候不常用小数,感兴趣的同学可以执行我下面的程序,会有意外收获,提示: 精度)
[code]#include "stdio.h" int main() { if (0.6f == 0.6f) printf("0.6f == 0.6f\n"); else printf("0.6f != 0.6f\n"); if (0.6d == 0.6f) printf("0.6d == 0.6f\n"); else printf("0.6d != 0.6f\n"); if (0.5f == 0.5f) printf("0.5f == 0.5f\n"); else printf("0.5f != 0.5f\n"); if (0.5d == 0.5f) printf("0.5d == 0.5f\n"); else printf("0.5d != 0.5f\n"); return 0; }
这里顺带提一下c++的四种类型转换:
这四种转换的用法一致:如
[code]int a = (int)0.2f; int a = ***_cast<int>(0.2f)
有点像函数,而里面的<int>,有点像<T>模版
类型 | 含义 |
---|---|
static_cast | 其实就是常见的类型转换,类似于 int a = (int)1.2f 在转换的过程中由于精度四舍五入,自然可能会损失数据 |
reinterpreter_cast | 是将数据重新解释,类似于上文的IP decoder,由于是只是重新解释二进制数据,所以不会造成数据的损失 |
const_cast | 将const指针(或引用)类型转换为非const指针(或引用)指针const意味着什么 |
dynamic_cast | 多态类型转换常用,具有类型检查功能,一般用于下行转换(基类转为派生类) |
其实C++的四种类型转换是普通类型转换的俩种普例+俩种特例,附带某些功能(如去除const,类型检查)。
附:
const测试:
[code]#include "stdio.h" int main() { int num1 = 1; const int *a = &num1; printf("a is %d\n", *a); num1 ++; printf("num1++, a is %d\n", *a); int num2 = 10; a = &num2; printf("a is %d\n", *a); // int *b = a; //error: invalid conversion from 'const int*' to 'int*' [-fpermissive] int *b = const_cast<int*>(a); // *a = *a + 1; //error: assignment of read-only location '* a' // printf("a is %d\n", *a); *b = *b + 1; printf("b is %d\n", *b); printf("a is %d\n", *a); return 0; } /** a is 1 num1++, a is 2 a is 10 b is 11 a is 11 **/ int main() { int num1 = 1; int * const a = &num1; printf("a is %d\n", *a); num1 ++; printf("num1++, a is %d\n", *a); // int num2 = 10; // a = &num2; //error: assignment of read-only variable 'a' // printf("a is %d\n", *a); int *b = a; *a = *a + 1; printf("a is %d\n", *a); *b = *b + 1; printf("b is %d\n", *b); return 0; } /** a is 1 num1++, a is 2 a is 3 b is 4 **/
const int * p | int * const p |
---|---|
p is a (pointer to)(*) const int | p is a const (pointer to)(*) int |
read-only ‘* a’(内容) | read-only ‘a’(指针) |
对于int * const p 不能修改p的指向(*p的地址、p变量的内容),但是可以修改*p的内容,虽然不能跟换p的指向(另一个烂例子:你住的地方不好更改,但是你可以布置一下家居)
相关文章推荐
- 精彩的人生早已开始,看你怎么看待你的人生了
- 动态规划:从新手到专家
- pull解析xml
- C++、PHP和Swoole
- tomcat升级问题
- 美团前端面试题及答案
- 【bzoj2761】bzoj大水题系列
- 1049 自增自减【水题】
- 代理
- Linux编译Qt提示Failure to find: FORMS
- 多线程编程
- 通知
- Node Buffer/Stream 内存策略分析
- 关于jquery定义对象的一种写法!
- tomcat JAVA启动参数 JAVA_OPTS
- 内核模块编译时出现的问题解决
- deploy zabbix 2.2.10 on ubuntu 14.04 64bit
- C++控制台应用程序之贪吃蛇(改进版)
- Android简单自定义标题栏
- 正则表达式