昨天碰到一个很奇怪的问题,首先来看这段代码:

 #include<stdio.h>
int main(int argc,char *argv[])
{
long num1 = ;
long long num2 = ; long long res1 = num1 * num1;
long long res2 = num2 * num2; printf("res1 = %lld\n",res1);
printf("res2 = %lld\n",res2); return ;
}

  程序的运行结果如下:

  

  这里感觉很奇怪,203879并没有超过4个字节的范围,但是它的平方超过了,于是我把它的结果存放在一个8字节数中,为什么最终结果还是显示溢出了呢?

  然后我又写了一段程序,把它的汇编代码拿出来分析了一下?程序如下:

 int main(int argc,char *argv[])
{
long muln = ;
long long mulnl = ; long long num1 = * ;
long long num2 = muln * muln;
long long num3 = mulnl * mulnl; return ;
}

  这里我分成三种情况,一种是直接的一个整数当乘数,一个是long型的整数当乘数,还有一个是long long型的整数当作乘数,然后分别计算他们的平方,我用gdb调试的结果如下:

  

  其中前两种情况都溢出了,只有第三种情况正常。然后我们再来查看一下他们的汇编代码,这是我用objdump反汇编出来的汇编代码:

  

 int main(int argc,char *argv[])
{
: push %ebp
: e5 mov %esp,%ebp
: e4 f8 and $0xfffffff8,%esp
804839a: ec sub $0x30,%esp
long muln = ;
804839d: c7 0c 1c movl $0x31c67,0xc(%esp)
80483a4:
long long mulnl = ;
80483a5: c7 1c movl $0x31c67,0x10(%esp)
80483ac:
80483ad: c7 movl $0x0,0x14(%esp)
80483b4: long long num1 = * ;
80483b5: c7 b1 movl $0xad90b171,0x18(%esp)
80483bc: ad
80483bd: c7 1c ff ff ff movl $0xffffffff,0x1c(%esp)
80483c4: ff
long long num2 = muln * muln;
80483c5: 8b 0c mov 0xc(%esp),%eax
80483c9: 0f af 0c imul 0xc(%esp),%eax
80483ce: c2 mov %eax,%edx
80483d0: c1 fa 1f sar $0x1f,%edx
80483d3: mov %eax,0x20(%esp)
80483d7: mov %edx,0x24(%esp)
long long num3 = mulnl * mulnl;
80483db: 8b mov 0x14(%esp),%eax
80483df: c1 mov %eax,%ecx
80483e1: 0f af 4c imul 0x10(%esp),%ecx
80483e6: 8b mov 0x14(%esp),%eax
80483ea: 0f af imul 0x10(%esp),%eax
80483ef: c1 add %eax,%ecx
80483f1: 8b mov 0x10(%esp),%eax
80483f5: f7 mull 0x10(%esp)
80483f9: d1 add %edx,%ecx
80483fb: ca mov %ecx,%edx
80483fd: mov %eax,0x28(%esp)
: 2c mov %edx,0x2c(%esp)
: mov %eax,0x28(%esp)
: 2c mov %edx,0x2c(%esp) return ;
804840d: b8 mov $0x0,%eax
}

  首先来看num1的代码(16~20行),203879(31C67H)平方为41566646641(9AD90B171H),编译器直接把这个结果计算了出来,然后取出结果的4个字节,存放到了num1中,然后再用符号位来填充高4字节。

  接下来我们再来看num2的代码(21~27行),首先它把203879存放到eax里面,再把相乘的平方结果存放到eax里面,由于eax是32位,所以存放的时候就舍去了高4位,只存放了低4个字节。接下来做的就是判断这个数的符号位是什么,然后再用移位运算得到32个1存放在edx里面,最后再把这个edx的值存放到num2的高四个字节里面。

  OK,通过上面这段汇编代码分析,我们再来从C语言的概念上来分析这句代码:

  long long num2 = muln * muln ;

  首先muln是一个4字节的整数,然后muln * muln得到的结果也是一个四字节的整数(这里产生了溢出),然后再把这个结果转换成8字节的整数,存放到num2中。所以我们最终得到的结果也是一个溢出的结果。

  分析完了之后,发现我这是舍进求远啊,现在也不知怎么了,遇到点啥就喜欢反汇编出来看看。。。

从一个乘法来分析C语言的更多相关文章

  1. C++写一个简单的解析器(分析C语言)

    该方案实现了一个分析C语言的词法分析+解析. 注意: 1.简单语法,部分秕.它可以在本文法的基础上进行扩展,此过程使用自上而下LL(1)语法. 2.自己主动能达到求First 集和 Follow 集. ...

  2. Go将统治下一个10年?Go语言发展现状分析

    “本文是国内Go语言大中华区首席布道师——许式伟,在QCon2015上海站上的分享.他预测Go语言10年内一定会超过C和java,并且统治这一个10年. Go语言语法及标准库变化 Go从1.0版本到现 ...

  3. 《C专家编程》第三章——分析C语言的声明

    前面一章我们已经说过C语言存在的一些问题和它晦涩的地方,让我们对这门神奇的语言有了更深的了解.现在这一章则集中精力来讨论C语言的声明,分为三块,首先是说明C语言声明晦涩难懂的原因和声明是如何形成的,其 ...

  4. 基于Spark和SparkSQL的NetFlow流量的初步分析——scala语言

    基于Spark和SparkSQL的NetFlow流量的初步分析--scala语言 标签: NetFlow Spark SparkSQL 本文主要是介绍如何使用Spark做一些简单的NetFlow数据的 ...

  5. 以杨辉三角为例,从内存角度简单分析C语言中的动态二维数组

    学C语言,一定绕不过指针这一大难关,而指针最让人头疼的就是各种指向关系,一阶的指针还比较容易掌握,但一旦阶数一高,就很容易理不清楚其中的指向关系,现在我将通过杨辉三角为例,我会用四种方法从内存的角度简 ...

  6. AI 的下一个重大挑战:理解语言的细微差别

    简评:人类语言非常博大精妙,同一句话在不同的语境下,就有不同的含义.连人类有时候都不能辨别其中细微的差别,机器能吗?这就是人工智能的下一个巨大挑战:理解语言的细微差别.本文原作者是 Salesforc ...

  7. 框架源码系列四:手写Spring-配置(为什么要提供配置的方法、选择什么样的配置方式、配置方式的工作过程是怎样的、分步骤一个一个的去分析和设计)

    一.为什么要提供配置的方法 经过前面的手写Spring IOC.手写Spring DI.手写Spring AOP,我们知道要创建一个bean对象,需要用户先定义好bean,然后注册到bean工厂才能创 ...

  8. 32 Profiling Go Programs 分析go语言项目

    Profiling Go Programs  分析go语言项目 24 June 2011 At Scala Days 2011, Robert Hundt presented a paper titl ...

  9. 18 A GIF decoder: an exercise in Go interfaces 一个GIF解码器:go语言接口训练

    A GIF decoder: an exercise in Go interfaces  一个GIF解码器:go语言接口训练 25 May 2011 Introduction At the Googl ...

随机推荐

  1. ABAP 日期时间函数(转)

    转自:http://www.sapjx.com/abap-datetime-function.html 函数名称 (内页-点击名称可查看操作) 函数说明 备注 FIMA_DATE_CREATE RP_ ...

  2. Exploring Python Code Objects

    Exploring Python Code Objects https://late.am/post/2012/03/26/exploring-python-code-objects.html Ins ...

  3. SVN 冲突文件快速解决方法

    精简的美丽...... 现在几乎没有几个写代码的人不用snv来存储代码了吧! 但是,在实际操作中,多人对同一文件读写造成冲突是时有发生的事.这个时候解决的方法就是打开文件找出冲突的地方.如果冲突的部分 ...

  4. python中文处理之encode/decode函数

    python中文处理相信迷惑过不少同学.下面说说python2/3的encode和decode函数. python2中,使用decode()和encode()来进行解码和编码,以unicode类型作为 ...

  5. jq选择器 第一部分

    没有什么新意,全是从网上摘抄的,如果哪天忘了,就来查查吧. 1. id选择器(指定id元素) 将id="one"的元素背景色设置为黑色.(id选择器返单个元素) $(documen ...

  6. Python学习笔记 第一课 列表

    Python的列表就像是一个数组: 一.创建列表 movies=["The Holy Grail","Then Life of Brian","The ...

  7. Windows环境下安装导入tornado

    首先,一台安装并配置好了python,我的python版本的肯定是2.7,直接进入tornado的环节: 下载tornado的压缩包,我的下载地址为:https://codeload.github.c ...

  8. Angular 2 从0到1 (三)

    作者:王芃 wpcfan@gmail.com 第一节:Angular 2.0 从0到1 (一)第二节:Angular 2.0 从0到1 (二)第三节:Angular 2.0 从0到1 (三)第四节:A ...

  9. css水平居中总结

    前言 看了好多篇帖子,发现没有一个能够直接让新手很快上手使用水平居中布局的,所以在此进行一番总结,也算是我对水平居中布局的一点点积累沉淀,同时也方便初学者们拿来即用. 一.元素分类 1.行内元素 行内 ...

  10. css hack 大全 各个浏览器的css

    各个浏览器的css hack区别属性: IE6: _zoom:1; IE6/7: *zoom:1; IE6/7/8/9 :\9 各个浏览器的css hack区别规则 IE6: *html{} IE7: ...