源码1

#include <stdio.h>
void f1() {
double x = -5.5625;
printf("%d\n",x); //输出为0,为什么?
}
int main() {
f1();
return ;
}

源码2

#include <stdio.h>
void f1() {
int y=;
printf("%f\n",y); //输出的值是随机的, 为什么?
}
int main() {
f1();
return ;
}

以下是利用gdb跟踪调试源码1的过程, 发现, printf("%d\n",x);根本就没有把x由double类型转换为int类型, 只是截取了x的低4个字节, 并输出

(gdb) b main
(gdb) r
Breakpoint , main () at .c:
f1();
(gdb) display /i $pc
call 0x8048354
(gdb) si
push �p ;保存上层函数的栈的上下文
(gdb) si
mov %esp,�p ;保存上层函数的栈的上下文
(gdb) si
sub $0x28,%esp ;为函数f1分配的栈,大小为28字节
(gdb) si
double x = -5.5625;
fldl 0x8048480 ;把0x8048480存储的双精度浮点数置入浮点寄存器%st()
(gdb) p/x (char[])*0x8048480
$ = {0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x16, 0xc0} ;证明了内存0x8048480处存储常量-5.5625
(gdb) si
double x = -5.5625;
fstpl 0xfffffff8(�p) ;把浮点寄存器%st()的值置入内存(�p-)处
(gdb) info all-registers
st0 -5.5625 (raw 0xc001b200000000000000) ;证明了%st()存储的浮点数为-5.5625
(gdb) si
printf("%x\n",x);
fldl 0xfffffff8(�p) ;把内存(�p-)处的双精度浮点数置入%st(),即-5.526
(gdb)
printf("%x\n",x);
fstpl 0x4(%esp) ;把%st()中的值置入内存(%esp+),即把printf的第二参数压栈
(gdb) i r esp
esp 0xbfb00320 0xbfb00320
(gdb) p/x (char[])*0xbfb00324
$ = {0x6c, 0x95, 0x4, 0x8, 0x38, 0x3, 0xb0, 0xbf}
(gdb) si
printf("%x\n",x);
movl $0x8048478,(%esp) ;把函数printf的第一个参数压入栈中,用栈来传递参数
(gdb) p/x (char[])*0xbfb00324
;显示printf的第二个参数的值。printf的格式串中”%d”在指明第二参数是int类型,即使实际传递的;是double类型,也没有进行类型转换,即没有把x由double类型转换为int类型,printf在取值是
;直接读取前4个字节00 ,所以printf输出为0
$ = {0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x16, 0xc0} ;
(gdb) si
printf("%x\n",x);
call 0x8048298 ;调用printf函数
(gdb) p/x (char[])*0xbfb00324
$ = {0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x16, 0xc0}

  由此引申开来发现如下规律:

    %d/%x/%u --> float/double: 利用%d/%x/%u输出float/double类型变量时, 会得到意想不到的结果, 因为不会进行类型转换, 而是把变量截断为4个字节并输出, 原因在前面已经给出

    %f --> int  利用%f输出int变量, 输出的值是随机的

void f1() {
int x = ;
printf("%f\n",x); ;输出的值是随机的
}

    对应的汇编代码:

movl    $, -(�p)
movl -(�p), �x
movl �x, (%esp) ;没有把x转换为float类型
movl $.LC0, (%esp)
;printf会读取内存4(%esp)除的8个字节,由于后4个字节的值是随机的,所以输出的值是随机的
call printf

    %d/%x/%u  --> char/short

    利用%d/%x/%u输出char/short类型变量时, 会对char/short类型进行符号位扩展, 扩展为4个字节

void f1(){
char x = 0x80;
printf("%x\n",x);
}

    对应汇编代码:

movb    $, -(�p)
movsbl -(�p),�x ;把x符号扩展为4个字节
movl �x, (%esp)
movl $.LC0, (%esp)
call printf

C-printf/sprintf/snprintf中的类型转换详解的更多相关文章

  1. 【转】linux 中fork()函数详解

    在看多线程的时候看到了这个函数,于是学习了下,下面文章写的通俗易懂,于是就开心的看完了,最后还是很愉快的算出了他最后一个问题. linux 中fork()函数详解 一.fork入门知识 一个进程,包括 ...

  2. Java类型转换详解

    Java类型转换详解 最近有同学问:自动类型转换老是记不住,到底是大转小,还是小转大 其实这个不用死记硬背,很好理解,我们拿 int 和 short 来举例: int 是 4 字节,也就是 32 bi ...

  3. php中关于引用(&)详解

    php中关于引用(&)详解 php的引用(就是在变量或者函数.对象等前面加上&符号) 在PHP 中引用的意思是:不同的变量名访问同一个变量内容. 与C语言中的指针是有差别的.C语言中的 ...

  4. JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解

    二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...

  5. AngularJS select中ngOptions用法详解

    AngularJS select中ngOptions用法详解   一.用法 ngOption针对不同类型的数据源有不同的用法,主要体现在数组和对象上. 数组: label for value in a ...

  6. 【转载】C/C++中extern关键字详解

    1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...

  7. oracle中imp命令详解 .

    转自http://www.cnblogs.com/songdavid/articles/2435439.html oracle中imp命令详解 Oracle的导入实用程序(Import utility ...

  8. Android中Service(服务)详解

    http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...

  9. python中threading模块详解(一)

    python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...

随机推荐

  1. foreach 与 Linq的 Select 效率问题

    Resharper 是一个非常强大的C#编程辅助工具,有着非常强的提示功能,代码纠正,代码简化等等 在编码过程中注意到这么一件事,可能是大家经常会遇到的: 遍历某个集合,然后经过处理生成另外一个集合, ...

  2. Vue CLI3 关闭热替换后出现的warning

    用vue cli3做项目的时候如果开启了typescript的严格模式,在dev server热替换的时候往往就会打出一大堆warning,严重的影响了编译效率.官方并没有提供关闭warning的ap ...

  3. kattis Curious Cupid (莫队算法)

    Curious Cupid There are K different languages in the world. Each person speaks one and only one lang ...

  4. Linux命令之halt、poweroff、reboot

    halt [选项] poweroff [选项] reboot [选项] 这三个命令模式一样,目的是引导内核启动或停止系统的运行:当没有-f参数或系统运行级别不是0和6,将执行/sbin/shutdow ...

  5. IDL软件初步了解

    软件名称:IDL(交互式数据语言Interactive Data Language) 软件类别:是国产软件,语言类,数据分析类,数据可视化类 语言类别:解释型 作用:可以进行数据处理的可视化等,在大数 ...

  6. [HNOI2018]道路(DP)

    题目描述 W 国的交通呈一棵树的形状.W 国一共有n−1n - 1n−1 个城市和nnn 个乡村,其中城市从111 到n−1n - 1n−1 编号,乡村从111 到nnn 编号,且111 号城市是首都 ...

  7. 【动态规划】bzoj1638 [Usaco2007 Mar]Cow Traffic 奶牛交通

    设f[u]为从度数0到u的路径条数,f2[u]为从u到n的路径条数. ans=max{f[x[i]]*f2[y[i]]}(1<=i<=m). #include<cstdio> ...

  8. [CF413D]2048

    题目大意: 在一个长度为$n(n\le2000)$的数组中填数$2$或$4$,待所有数字全部填好后,按照类似于2048的规则向左合并.给定某些格子上的数,问在当前情况下要使得合并后的最大数超过$2^k ...

  9. FCL研究-集合- System.Collections 接口和对象集合

    [目录] 发现自己已经有很长一段时间写代码没什么进步了,随便读读FCL的源码,看看之前一直用的方法是如何实现的,也顺便提高下自己.FCL很是庞大,很难下口,于是用最笨的办法,先看常见的命名空间,逐个展 ...

  10. Java使用POM一JAR包的形式管理JavaScript文件-WebJars

    说明:原来JS框架还可以使用POM进行管理的.WebJars是一个很神奇的东西,可以让大家以JAR包的形式来使用前端的各种框架.组件. 什么是WebJars 什么是WebJars?WebJars是将客 ...