为什么printf()在这段代码中打印出来?

use*_*943 -1 c printf

这个简单的代码令我感到困惑 - 我故意打印出比传递给printf更多的整数.我预计会出错.我得到了奇怪的数字 - 它们来自哪里?

#include <stdio.h>
/* learn arrays */
void main(){
    int pout;
    pout = 6;
    printf("%i %i %i\n%i %i %i\n%i %i %i\n", pout);
}
Run Code Online (Sandbox Code Playgroud)

输出的一个例子:

6 608728840 0
-885621664 -885543392 608728816
0 0 -889304251
Run Code Online (Sandbox Code Playgroud)

单个数字不会随着重复运行而改变,但是大整数会改变.

P1k*_*chu 6

这是printf字符串格式漏洞之一.你试图调用比实际更多的参数,所以printf在堆栈上采取他能做的任何事情.

它(并且仍然)非常习惯于利用程序来探索堆栈以访问隐藏信息或绕过身份验证.

查看堆栈

printf ("%08x %08x %08x %08x %08x\n"); 
Run Code Online (Sandbox Code Playgroud)

这指示printf函数从堆栈中检索五个参数并将它们显示为8位填充的十六进制数字.所以可能的输出可能如下所示:

40012980 080628c4 bffff7a4 00000005 08059c04

更完整的解释.

  • OP询问数字的来源,以及实际发生的情况.你的答案没错,但不完整.这是我投票的唯一原因,不是因为我没有投票也没有投票.:) (2认同)

Iha*_*imi 5

因为它是未定义的行为.如果说明符的数量大于匹配参数的数量或它们的类型不兼容,则行为未定义.

这个qoute来自c11标准草案

7.21.6.1 fprintf功能

  1. fprintf函数在format指向的字符串的控制下将输出写入stream指向的流,该格式指定后续参数如何转换为输出.如果格式的参数不足,则行为未定义.如果参数保留时格式已用尽,则会评估多余的参数(一如既往),否则将被忽略.遇到格式字符串的末尾时,fprintf函数返回.

  1. 如果转换规范无效,则行为未定义.282) 如果任何参数不是相应转换规范的正确类型,则行为未定义.

我强调了相关部分,使它们变得大胆.

  • 把它转化为人类说话,当C或C++中的某些构造具有未定义的行为时,任何事情都可能发生,包括外星人绑架你的孩子,这将是你的错,而不是编译器.然而,大多数编译器会让程序执行一些不那么开放的行为,就像@ Mr.St4N的回答中描述的那样. (2认同)