6

或者换句话说:错误的printf/fprintf十进制整数 ( %d, %u, %ld, %lld) 格式字符串会导致程序崩溃或导致未定义的行为吗?

Cosinder 以下代码行:

#include <iostream>
#include <cstdio>

int main() {
    std::cout << sizeof(int) << std::endl
              << sizeof(long) << std::endl;

    long a = 10;
    long b = 20;
    std::printf("%d, %d\n", a, b);

    return 0;
}

32 位架构的结果:

4
4
10, 20

64 位架构的结果:

4
8
10, 20

在任何情况下,程序都会打印出预期的结果。我知道,如果long值超出int范围,程序会打印错误的数字——这很难看,但不会影响程序的主要目的——但除此之外,还会发生什么意外吗?

4

5 回答 5

8

如果使用错误的格式字符串调用 printf 会发生什么?

任何事情都有可能发生。这是未定义的行为!
未定义的行为意味着任何事情都可能发生。它可能会向您显示您期望的结果,也可能不会或可能会崩溃。任何事情都有可能发生,除了你自己,你不能责怪任何人。

参考:

c99 标准:7.19.6.1:
第 9 段:

如果转换规范无效,则行为未定义。225)如果任何参数不是对应覆盖规范的正确类型,则行为未定义。

于 2013-01-24T14:53:48.527 回答
3

这是未定义的行为——规范中没有任何内容告诉编译器设计者(或 C 库设计者)应该如何处理,因此他们可以做任何事情。

在实践中,这是完全取决于对数字的解释的那些之一,而且很可能,这样做你永远不会得到任何好处。真正糟糕的是当您将字符串与整数格式混合时 - 字符串将很好地打印为(可能是奇怪的)数字,但数字在作为字符串传递时不太可能“工作” - 因为字符串是指向第一个地址的指针字符 - 并且大多数数字在典型系统中都不是有效的指针,因此它会崩溃。

但是没有任何保证。在您的 64 位示例中,很明显该数字是“小端”。用 0x100000000 尝试同样的事情,它会打印 0 - 因为其余的数字都丢失了。

于 2013-01-24T14:57:41.800 回答
2

哦,是的 - printf 取决于格式字符串来确定接下来要获取的变量的大小和类型。当格式字符串错误时,它可能会尝试获取甚至不存在的变量,并可能产生所有后果。

于 2013-01-24T14:55:34.690 回答
2

如果使用错误的格式字符串调用 printf,任何事情都可能发生。它的未定义行为,永远不应该依赖未定义的行为。

于 2017-03-11T07:19:24.310 回答
-2

不要使用 printf

printf是 C 时代的遗物,不再需要...改用std::coutI/O 操纵器。

于 2013-01-24T15:05:52.713 回答