整形提升与溢出
来源:互联网 发布:中日技术贸易 数据 编辑:程序博客网 时间:2024/05/11 21:08
1、整形提升
表达式进行计算时,变量如果能用int表示,就用int表示,如果不能用int表示,就用usigned int表示。
这是因为寄存器的长度和int长度一致。
到底是用int还是unsigned int,取决于编译器。举一个例子:
char c = 0xb0;
if(c==0xb0){
...
}
c在参与运算的时候, 0xb0 = 01011 00000, 编译器会解释上述代码为:
mov al, 0xb0
movsz edx, al //将al进行带符号扩展,扩展完成后0xff ff ff b0
cmp edx, 0xb0 //将0xff ff ff b0 和0xb0,进行32位比较,不等恒成立。
2、整形溢出
根据规则1, 计算机运算都可理解成整形的运算,其他类型的一般都会进行符号位扩展成32位进行运算,那么溢出规则可以简单的理解为:
2.1 无符号的整形溢出规则
结果 = 理论值 mod (2 ^ 寄存器长度),也可以简单理解为高位舍弃。
假设CPU为8位机, 定义2个char类型的变量:
x = 130; y = 131;
由于寄存器最大长度8, 则最大能表示的255, 而x+y =261 = 0b1 0000 0101
结果 = 261 mod (2 ^ 8) = 5, 或者理解为 0b1 0000 0101 舍弃高位:0b101 = 5
2.2 有符号整形溢出规则
在各个平台上支持不一样,C语言规定为不可预测。(经测试,在x86上也是高位舍弃)
3、例子分析
int main(){char c = -20;unsigned int a = 6;printf("%d\n", ((c+a)>1));}
输出居然为-14, 1,不理解? 看汇编
c的机器码为:0xec, 由于字符在内存中是以数字存贮的,且只占一个字节,在整形提升中,为保证数字值不变,高位全部扩展为1,那么, (c+a)= oxfffffff2 >1 成立。因为cpu是通过补码运算,实际cpu运算有兴趣的可以自己验证。
例二:
int main(){char c = -20;int a = 6; //去掉unsignedprintf("%d\n", ((c+a)>1));}
区别只在于 例子1后面调用setg, 例子二调用的seta
seta al含义:al = ~CF & ~ZF = 1
setg al含义: al = ~(SF ^OF) & ZF = ~(1 ^ 0) & 0 = 0
从这个例子可以也看出, 所谓整形提升,以及所谓的有符号和无符号相加的问题,都只与编译器有关,编译器根据语法规则生成对应体系架构的机器码,
CPU在其中的作用,只是进行运算以及运算中对各个标志位赋值而已。
- 整形提升与溢出
- 溢出与类型提升
- 数据溢出与类型提升
- c++ 整形 提升
- c的整形转换和整形提升
- C\C++中的整形提升
- C语言 — 整形提升
- c语言中的整形提升
- 典型的整形溢出行为
- 两个整形相加,相乘(有检测溢出)
- 关于leetcode中整形溢出的几道题。
- 关于整形溢出(转载至CollShell)
- CSS 整形与优化
- 字符串与整形转换
- Redis 与网络流量整形
- C语言中的算数转换和整形提升
- 小细节:说说整形提升(Integral promotions)
- 有序整形数组,提升效率的折半查找算法
- Git学习笔记(一)
- web前端优化
- java初学者从这里开始
- Header Manipulation
- eclipse打不开试试这个
- 整形提升与溢出
- 用例和功能的区别
- 表单控件状态(禁用状态)
- [UnityShader]Blending
- Insecure Randomness
- java gc及jvm调优
- 查找单链表的倒数第K个元素
- nyoj zb的生日 (DFS)
- 基于Ubuntu 15.04 LTS编译Android5.1.0源代码