如何停止 printf 根据顺序生成不同的值?

发布于 2024-11-01 08:05:39 字数 635 浏览 1 评论 0原文

Code:

#include <stdio.h>

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

Output: 1.000000, 1072693248, 0,

Code:

#include <stdio.h>

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

Output: 3ff00000, 0.000000, 0

Code:

#include <stdio.h>

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

Output: 3ff00000, 0, 1.000000

这只是 %u 和 %x 消耗的字节数的问题吗?我该如何解决让价值观变得一致?

Code:

#include <stdio.h>

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

Output: 1.000000, 1072693248, 0,

Code:

#include <stdio.h>

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

Output: 3ff00000, 0.000000, 0

Code:

#include <stdio.h>

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

Output: 3ff00000, 0, 1.000000

Is this just an issue with the number of bytes that %u and %x consume, and how do I get the values to become consistent?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

短暂陪伴 2024-11-08 08:05:39

正如您所注意到的,传递类型与格式字符串的相应组件不匹配的参数将导致未定义的结果。特别是,"%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);

Passing arguments whose type does not match the corresponding component of the format string will lead to undefined results, as you've noticed. In particular, "%x" and "%u" both expect values of type (unsigned) int. Passing a float (which will often actually be represented as a double or long double depending on the ABI) is semantically incorrect.

Your compiler should be warning you about this - if not, make sure you've got all warnings enabled (-Wall for GCC).

If you want 1.0f as an integer, just cast:

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

If you're trying to obtain the binary representations, try something like this:

float a = 1.0f;
printf(" %x, %u, %f\n", *((unsigned*)&a), *((unsigned*)&a), a);
乖不如嘢 2024-11-08 08:05:39

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

printf 的手册页 包含创建正确格式字符串所需的所有详细信息您要打印的值。

You tell printf what arguments to expect via the first parameter: the format string. The additional values you pass to printf must match the format string. If they don't you get garbage output. In your examples, you are passing a floating point vale 1.0f and you're telling printf to treat it as an integer with %u format specifier. You thus get garbage output.

The man page for printf has all of the details you need to create the correct format string for the values you want to print.

清风疏影 2024-11-08 08:05:39

你不能。

每个格式字段都期望与格式说明符指定的类型完全相同。

在 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 时,浮点值甚至可能是无效的,这可能会导致崩溃)。

如果您想了解有关变量参数列表的更多信息,请查看传递变量参数中的答案在 C 中

You can't.

Every format-field expects exactly the same type as specified by the format-specifier.

On x86 systems, arguments are often passed on the stack, and using an incorrect format-specifier will cause the variable-argument functionality to take the wrong number of bytes from the stack.

In your case, you call printf with 3 floating point values, but floating point values are promoted to double (see http://en.wikipedia.org/wiki/Type_conversion#Type_promotion_in_C-like_languages).
So in this case (on x86 systems), there will be 3 times 8 bytes on the stack.

The first format-field will take the number of bytes it expects on the stack:

  • %x will take 4 bytes
  • %u will also take 4 bytes
  • %f will take 8 bytes

So the order of the format-fields will have an influence on the actual data that is printed. (with %f it is even possible that the floating-point value is an invalid one, which may cause a crash).

If you want to know more about variable argument lists, look at the answers in Passing of variable arguments in C

拔了角的鹿 2024-11-08 08:05:39

当我用 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 浮点说明符。给定浮点数,这总是会给出一致的结果。

When I compile this with gcc I get the following warnings:

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’

This is why you get the garbage output that you are using. It's a good idea to compile with the strictest warnings possible so you can get early notice of problems like this.

%u and %x are format specifiers that expect unsigned integers. You should be using the %f floating point specifiers for all of the examples. This would always give consistent results given floating point numbers.

萝莉病 2024-11-08 08:05:39

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

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

This is issue with argument list do not match format descriptors. If you want to print 1.0f as integer value, convert it to integer first:

printf("%x, %u, %f,\n", (int)1.0f, (int)1.0f, 1.0f);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文