如何根据订单停止printf生成不同的值?

时间:2011-04-13 10:07:20

标签: c printf

代码:

#include <stdio.h>

int main()
{
    printf(
            " %f, %u, %x,\n", 1.0f, 1.0f, 1.0f);
    return 0;
}

输出:1.000000,1072693248,0,

代码:

#include <stdio.h>

int main()
{
    printf(
            " %x, %f, %u,\n", 1.0f, 1.0f, 1.0f);
    return 0;
}

输出:3ff00000,0.000000,0

代码:

#include <stdio.h>

int main()
{
    printf(
            " %x, %u, %f,\n", 1.0f, 1.0f, 1.0f);
    return 0;
}

输出:3ff00000,0,1.000000

这只是%u和%x消耗的字节数问题,以及如何使值保持一致?

5 个答案:

答案 0 :(得分:3)

通过第一个参数告诉printf需要什么参数:格式字符串。传递给printf 的其他值必须与格式字符串匹配。如果他们不这样做你会得到垃圾输出。在您的示例中,您传递的是浮点值1.0f,并且您告诉printf将其视为具有%u格式说明符的整数。因此,你得到垃圾输出。

man page for printf包含为要打印的值创建正确格式字符串所需的所有详细信息。

答案 1 :(得分:3)

传递类型与格式字符串的相应组件不匹配的参数将导致未定义的结果,如您所注意到的那样。特别是,"%x""%u"都期望值类型(无符号)int。传递float(通常实际上表示为doublelong double取决于ABI)在语义上是不正确的。

您的编译器应该警告您 - 如果没有,请确保您已启用所有警告(GCC为-Wall)。

如果你想要1.0f作为整数,只需要转换:

printf(" %x, %u, %f\n", (unsigned)1.0f, (unsigned)1.0f, 1.0f);

如果您正在尝试获取二进制表示,请尝试以下操作:

float a = 1.0f;
printf(" %x, %u, %f\n", *((unsigned*)&a), *((unsigned*)&a), a);

答案 2 :(得分:2)

你不能。

每个format-field都需要与format-specifier指定的完全相同的类型。

在x86系统上,参数通常在堆栈上传递,并且使用不正确的格式说明符将导致变量参数功能从堆栈中获取错误的字节数。

在您的情况下,您使用3个浮点值调用printf,但浮点值将提升为double(请参阅http://en.wikipedia.org/wiki/Type_conversion#Type_promotion_in_C-like_languages)。 所以在这种情况下(在x86系统上),堆栈上将有3个8字节。

第一个格式字段将采用它在堆栈上预期的字节数:

  • %x将占用4个字节
  • %u也将占用4个字节
  • %f将占用8个字节

因此,格式字段的顺序将对打印的实际数据产生影响。 (使用%f,甚至可能浮点值是无效值,这可能会导致崩溃)。

如果您想了解有关变量参数列表的更多信息,请查看Passing of variable arguments in C

中的答案

答案 3 :(得分:1)

当我使用gcc编译它时,我收到以下警告:

crazy.c: In function ‘main’:
crazy.c:4: warning: format ‘%u’ expects type ‘unsigned int’, but argument 3 has type ‘double’
crazy.c:4: warning: format ‘%x’ expects type ‘unsigned int’, but argument 4 has type ‘double’
crazy.c:5: warning: format ‘%x’ expects type ‘unsigned int’, but argument 2 has type ‘double’
crazy.c:5: warning: format ‘%u’ expects type ‘unsigned int’, but argument 4 has type ‘double’
crazy.c:6: warning: format ‘%x’ expects type ‘unsigned int’, but argument 2 has type ‘double’
crazy.c:6: warning: format ‘%u’ expects type ‘unsigned int’, but argument 3 has type ‘double’

这就是您获得正在使用的垃圾输出的原因。用最严格的警告进行编译是个好主意,这样你就可以及早发现这类问题。

%u%x是期​​望无符号整数的格式说明符。您应该为所有示例使用%f浮点说明符。给定浮点数,这总是给出一致的结果。

答案 4 :(得分:0)

这是参数列表与格式描述符不匹配的问题。如果要将1.0f打印为整数值,请先将其转换为整数:

printf("%x, %u, %f,\n", (int)1.0f, (int)1.0f, 1.0f);