printf语句中的不同数据类型变量如何在打印顺序中相对地相互影响

时间:2014-04-18 08:23:42

标签: c printf

当我执行此代码段时:

void main(){
    float a=3;
    int b=5;
    printf( "%d %d \n", a, b);
}

我的输出为

0 1074266112 

当我改变打印顺序时,即

printf("%d %d \n",b,a);

我得到了这个输出:

5 0

为什么?

6 个答案:

答案 0 :(得分:3)

由于您的说明符与实际值不匹配,因此您将调用未定义的行为。这意味着任何事情都可能发生,特别是,行为可能会在程序调用之间发生变化(如果格式说明符读取的数据多于实际提供的数据)或者至少在编译器设置之间。


内部可能发生的事情取决于许多因素,例如int值的长度等等。无论如何,这是你不能依赖的东西。

这里真正发生的是:float在传递给可变参数函数时自动提升为double,将其长度更改为8个字节。

我用这种方式修改了你的程序:

#include <stdio.h>

void main(){
    float a=3;
    int b=5;
    printf("%08x %08x %08x\n", a, b);
    printf("%08x %08x %08x\n", b, a);
    printf("%d %d %d\n", a, b);
    printf("%d %d %d\n", b, a);
}

给出输出

00000000 40080000 00000005
00000005 00000000 40080000
0 1074266112 5
5 0 1074266112

所以我们确切地看到值resp。字节通过堆栈传递给printf()。由于这些值由于字节序而被交换(当通过%08x解释时它们在视觉上交换),我真的有字节

00 00 00 00  00 00 08 40  05 00 00 00
05 00 00 00  00 00 00 00  00 00 08 40

如果我们现在使用错误的说明符,我们得到映射

00 00 00 00 -> 00000000 -> 0
00 00 08 40 -> 40080000 -> 1074266112
05 00 00 00 -> 00000005 -> 5

然后输出。

如果我省略一个%d,则也会省略相应的最后一个值,导致

0 1074266112
5 0

反过来。

所以你的b值似乎改变的原因是,在第一种情况下,你真的得到了&#34;其他&#34;您a值的一部分。

答案 1 :(得分:3)

您的代码在技术上会调用未定义的行为;两个产出背后仍有明确的逻辑。

它与可变功能和自动类型促销有关。

每次将浮点数传递给可变参数函数时,它都会自动提升为double。 printf说明符%f始终被解释为%lf。你可以自己试试,输出总是加倍。

第一个例子:

float a=3;
int b=5;
printf( "%d %d \n", a, b);

(int类型在你的系统上占用4个字节)

你传递一个float,它被提升为一个double并占用8个字节的堆栈,一个整数需要4个字节。然后你尝试在堆栈上打印前8个字节(两个4字节的%d),然后得到(现在)double的前4个和后4个字节。未读取的整数。

第二个例子:

printf( "%d %d \n", a, b);

这是不同的,因为您首先传递正确打印的整数,然后您只打印双精度的前4个字节。

答案 2 :(得分:2)

要回答您的问题,printf调用中的格式说明符不会相互影响,而是确定printf如何解释传递给它的相应参数的值。对于scanf调用也是如此。

对值使用错误的格式说明符是未定义的行为。因此,浮动变量%d的{​​{1}}转换说明符在这里是错误的。

a

未定义的行为意味着代码的行为是不可预测的。任何事情都可能发生从随机输出到程序崩溃到您的硬盘驱动器格式化。简而言之,行为无法理解,您应该始终避免编写此类代码。有关更多信息,请阅读这些 -

答案 3 :(得分:2)

首先是几个事实。

  1. 在32位系统上,当您指定"%d %d"时,printf期望 第一个int获得4个字节,第二个获得4个字节 int
  2. 当您将浮动传递给printf时,它会自动提升为 double,这意味着堆栈需要8个字节。
  3. 现在回答你的问题。

    在第一种调用printf( "%d %d \n", a, b);的情况下,程序将12个字节压入堆栈,8个字节用于float a,4个字节用于int b。因为您指定了%d %d,所以printf将占用a的前4个字节,并将其打印为第一个数字0。然后它将占用a的后4个字节并将其打印为第二个数字1074266112

    在第二种调用printf("%d %d \n",b,a);的情况下,程序将再次将12个字节压入堆栈,但这次是b的4个字节,然后是{{8个字节1}}。因此a正确显示printf,然后将b的前4个字节显示为第二个数字a

答案 4 :(得分:0)

%d表示整数。

printf ( "floats: %4.2f %+.0e %E \n" , 3.1416, 3.1416, 3.1416); 

答案 5 :(得分:0)

当参数的强制转换为整数时,不执行浮点库或计算函数的值传递。 因此,它变成与假设不同的值。 例如,如果您显示的程序是由x86体系结构运行的情况,则只有mmx命令执行强制转换的值才能正确显示。 如果此操作的存在使用gcc,则最好给出“-S”选项。