当 printf 没有指定格式说明符时会发生啥?

Posted

技术标签:

【中文标题】当 printf 没有指定格式说明符时会发生啥?【英文标题】:What happens when a format specifier is not given to printf?当 printf 没有指定格式说明符时会发生什么? 【发布时间】:2014-01-26 22:52:03 【问题描述】:

我在 Careercup 中遇到过这个关于 printf 的问题。

char *str = "hello";
printf("%s",str);
printf(str);

第二个 printf 语句有时会崩溃。我检查了各种网站。编写程序,看看它是否确实如此。但事实并非如此。另外,我知道 printf 接受类型为“const char* format”的参数,但格式可以是任何常量字符串,如“hello”。但是如果我将它存储在一个字符串 str 中(它当然指向只读内存)。预计将以相同的方式工作。究竟会发生什么?

谁能给个详细的解释。

【问题讨论】:

它的工作方式完全相同。第一个参数始终被解释为格式字符串。 str 变量不包含%something 占位符... 我看不到第二条语句会如何崩溃,除非 str 不是以 null 终止的。 @cup 如果第二个语句包含参数说明符,则它可能会崩溃,因为没有参数。 【参考方案1】:

格式字符串中的格式说明符不是必需的,因此:

printf("%s", "Hello world\n");

printf("Hello world\n");

将产生相同的行为。

但是如果字符串在:

printf(str);

来自用户输入,您应该使用%s 说明符,否则您很容易受到格式化字符串攻击(攻击者可以使用%x 伪造字符串来转储堆栈,使用%n 来覆盖内存)。

【讨论】:

【参考方案2】:

使用动态格式字符串调用printf 一般是不安全的:

void foo(char const * p)

    printf(p);   // !

您无法仅从程序源代码判断程序是否正确。正确性取决于字符串的(即它不能包含格式说明符),它可能是未定义的行为。

这是该语言的不安全方面之一:您正在放弃类型系统(因为变量参数),因此您放弃了静态正确性可验证性。

从字面上打印字符串的安全方法是fputs(p, stdout),或者(可能效率较低)printf("%s", p)

【讨论】:

【参考方案3】:
char *str = "hello";
printf(str);

相当于:

printf("hello");

就像:

char *format = "%s",
     *str = "hello";
printf(format, str);

相当于:

char *str = "hello";
printf("%s",str);

...而你能否真正依赖format的内容是完全不同的故事。

【讨论】:

以上是关于当 printf 没有指定格式说明符时会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

当返回对象的函数在没有返回语句的情况下结束时会发生啥

当删除没有虚拟析构函数的多态对象时会发生啥?

当调用winsock 中的recv 函数并且没有收到所有数据时会发生啥?

当一个方法没有被声明为 public、private 或 protected 时会发生啥? [复制]

当循环结束时会发生啥?

当堆栈和堆碰撞时会发生啥