如果我们打印一个包含“%s”的字符串,输出将是什么?

che*_*shi 7 c printf c-strings undefined

我想知道如果我们打印内容中包含“%s”的字符串会是什么结果?

我尝试将其打印为“ hi%s”。

char *ptr="hi%s";
printf(ptr);
Run Code Online (Sandbox Code Playgroud)

我希望输出为“ hi”。但我以“嗨,嗨,%s”的名字得到它。

“嗨,嗨,%s”

Cab*_*ion 11

如在其他答案中指定的那样,将发生未定义的行为。

在这种情况下,未定义行为的含义是:printf接收到带有n个格式说明符(例如%s)的字符串时,除了该字符串之外,还期望将n个参数传递给该函数。因此,当您具有这样的语句时printf("hi%s"),该函数的行为就好像您传递了一个参数一样(在这种情况下,第二个参数应为char *),即使没有。该函数只是要获取堆栈中的下一个值,在这种情况下,这是一些垃圾值。然后,该函数将引用该垃圾值,并将其视为字符缓冲区。未定义此行为的原因是无法确定堆栈上的垃圾值是多少。

可能的结果

  1. 取消引用垃圾值时,堆栈上的垃圾值为0->分段错误。

  2. 堆栈上的垃圾值恰好是有效的内存地址->内存位置的字节将一直插入到字符串中(在这种情况下,附加到“ hi”),直到遇到值0的字节或分段为止发生故障。

  3. 堆栈上的垃圾值不是0,但不是有效的内存位置->取消引用垃圾值时出现分段错误。

产生相同的情况 下面的代码部分与以下情况非常相似printf("hi%s")

void foo() {
   char * myJunkValue;  // Since not a global/static variable, this is not guaranteed to be 0
   printf(myJunkValue); // Undefined behavior
}
Run Code Online (Sandbox Code Playgroud)


Sou*_*osh 6

您的程序调用未定义的行为

您的代码等同于

 printf("hi%s");
Run Code Online (Sandbox Code Playgroud)

在哪里%s是一个转换说明符,它期望提供一个参数。

引用C11第§7.21.6.1章

[...]如果格式的参数不足,则行为未定义。[....]

建议:如果只需要打印字符串,而无需任何转换(格式化),则可以使用puts()


R..*_*R.. 5

您不是在“打印包含%s其内容的字符串”。您正在将诸如格式字符串之类的字符串传递给printf,并且这样做没有格式字段的匹配参数,则您的程序具有未定义的行为。的第一个参数printf不是您要打印的字符串。这是一个格式字符串,它控制如何解释/转换其余参数,并且还可以包含将其合并到其中的文字文本。

可以通过或来完成“打印包含%s其内容的字符串”(ptr指向该字符串,如您的问题所示)。printf("%s", ptr)puts(ptr)