博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C-printf/sprintf/snprintf中的类型转换详解
阅读量:6858 次
发布时间:2019-06-26

本文共 2551 字,大约阅读时间需要 8 分钟。

源码1

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

源码2

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

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

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

    对应的汇编代码:

movl    $1, -4(�p)  movl    -4(�p), �x  movl    �x, 4(%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    $1, -1(�p)  movsbl  -1(�p),�x  ;把x符号扩展为4个字节  movl    �x, 4(%esp)  movl    $.LC0, (%esp)  call    printf

 

 

转载地址:http://hljyl.baihongyu.com/

你可能感兴趣的文章
Dridex木马如何进行重定向攻击?
查看>>
《新编计算机科学概论》一0.3 计算机与社会
查看>>
“十三五”光伏行业将迎高速增长期 重点推动10方面工程
查看>>
中科院计算所开源Easy Machine Learning系统,用交互式图形界面简化ML开发过程
查看>>
专访陈孝良:智能音箱厂商很难逃脱为巨头打工的命运丨CCF-GAIR 2017
查看>>
如何用云计算模式,实现生物信息分析 | 硬创公开课
查看>>
焦烈焱|数字化经济时代
查看>>
《企业软件交付:敏捷与高效管理精要》——2.7 述评
查看>>
SCRM和传统的营销CRM到底有什么区别呢?
查看>>
《SAP后勤模块实施攻略—SAP在生产、采购、销售、物流中的应用》——3.3 MRP结果评估概览...
查看>>
Facebook承诺为普通市民提供1500套住房
查看>>
青岛推动大数据发展 政务大数据云中心2018年建成
查看>>
视觉追踪热图帮Instagram被吐槽新l
查看>>
大数据技术在商业银行中的应用:场景、优势与对策
查看>>
实施数据湖泊之前请先“试水”
查看>>
科技巨头的RFID平台大机会浅析
查看>>
组件价格跳水 光伏产品面临量价齐跌
查看>>
时光荏苒:你不知道的台湾光伏那些年
查看>>
提取电子数据也需关照公民隐私
查看>>
高通跻身无线路由器市场,想分一杯智能家居行业的羹
查看>>