c语言打印出奇怪字符,C语言中printf输出的奇怪错误

你留意一下标准库里面的stdarg.h文件,它里面定义了几个宏,分别是va_start、va_arg、va_end,这几个宏都是用来做不定参数传递的。特别注意的是va_arg在获取传递进来的参数时依赖它的第二个参数(t,类型),如果类型不对应的话会导致整个不定参数的传递没法正常的解析(错位)。prinft依赖于vsprintf,而vsprintf的实现依赖这几个宏,它会根据格式字符串(也就是那些%d %f ...)来调用va_arg,如果你的格式字符串和你后面的不定参数没有正确对应起来,那么也有可能在获取不定参数时出现错位(而你第二个输出对了两次也是因为错位了两次之后刚好又对上了的缘故)。

还有float(32位)参数在传递printf的时候会自动转换成double(64位)(这也是%f和%lf没区别的缘故),int参数占32位。

有了上面的铺垫之后,下面来解释你的这个问题。

环境:Windows XP 32, gcc version 3.4.0 (mingw special)

注:以下连续的十六进制数据从左到右对应于内存地址的由低到高

你传入的参数a,a,b,b,对应十六进制的00 00 00 00 00 00 04 40 00 00 00 00 00 00 04 40 02 00 00 00 02 00 00 00正确的分割应该是:

a: [00 00 00 00 00 00 04 40]

a: [00 00 00 00 00 00 04 40]

b: [02 00 00 00]

b: [02 00 00 00]

根据你的第一次输出的格式字符串,printf做了如下的分割:

%d: [00 00 00 00] int,对应0x00000000,也就是0了

%f: [00 00 04 40 00 00 00 00] double,0.0,(看double的表示法)

%d: [00 00 04 40] int,对应0x40040000,也就是10进制的1074003968

%f: [02 00 00 00 02 00 00 00] double,0.0

所以输出也就是:

0

0.000000

1074003968

0.000000

而根据你第二次输出的格式字符串,printf做了如下的分割:

%f: [00 00 00 00 00 00 04 40] double, 对应2.5

%d: [00 00 00 00] int 对应0

%f: [00 00 04 40 02 00 00 00] double,对应0

%d:[02 00 00 00] int 对应0

也就是你看到的:

2.500000

0

0.000000

2

至于为什么好几次double都变成0.0,你需要去看看IEEE的double表示标准。

简而言之就是:printf的在做输出的时候会根据格式字符串来获取传递进来的不定参数,而错误的格式字符串会导致不定参数的获取错误,从而导致输出错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值