是printf(c);是一个有效的语法(其中c是一个字符串文字)?

时间:2013-12-05 12:39:59

标签: c syntax arguments printf format-specifiers

我来到这个question并看到这一行

printf(&c[i]);  

我想知道,这是一个有效的语法吗?打印不带格式说明符%s的字符串/字符串文字不会导致未定义的行为约束违规
如果这是一个有效的语法,那么它的用途是什么?

我编译了这段代码

#include <stdio.h>

int main()
{
    char *c = "Hello World";

    printf(c);
    printf("\n\n");
    printf(&c[0]);

    return 0;
}  

并且在没有输出任何警告/错误的情况下进行编译

Hello World

Hello World

5 个答案:

答案 0 :(得分:3)

这是不明智的(特别是如果所说的字符串来自用户),但这不是非法的。

有关条款将是第7.19.6.1节第3段(强调我的):

  

格式应为多字节字符序列,以其初始移位状态开始和结束。格式由零或多个指令组成:普通的多字节字符(不是%),它们不加改变地复制到输出流中;和转换规范,每个都导致获取零个或多个后续参数,根据相应的转换说明符转换它们(如果适用),然后将结果写入输出流。

您应该使用fputs(c);fprintf("%s", c);来确保您的字符串不会被意外解释为包含指令。

答案 1 :(得分:1)

它有效,但不推荐。假设你有

char *c = "We have a 30%sale!";

然后,您的printf语句将访问垃圾内存,尝试解析%s

答案 2 :(得分:1)

使用printf不安全代码的主要示例:无法从源代码(特别是类型系统);正确性取决于而不是类型。这种代码可能的事实使C成为“不安全的语言”。例如:

void f(char const * p)
{
    printf("%s", p);      // this is safe!

    printf(p);            // correct if the string contains no format specifiers;
                          // undefined behaviour otherwise
}

重复:程序的正确性取决于其运行时特性,并且无法保证静态。

你永远不应该写这样的代码!

答案 3 :(得分:0)

这是允许的,但它有风险。考虑下面的一些功能。

void foo(const char* s) {
    printf(s);
}

如果输入参数中有%s之类的内容,它可能会生成核心。

答案 4 :(得分:0)

它有效,因为c是一个指向字符串开头的指针(换句话说,它是指向字符串第一个符号的指针)。 c[0]会为您提供一个字符W&让你指向这个char。您在代码中使用的构造只是通过指针获取值并立即返回此值的指针。例如,c[i]等于*(c+i)

为什么会这样?因为printf()函数接收一个指向string的指针作为参数。它会打印从指针开始到'\0'符号的所有符号。

请详细了解C语言中的指针以及如何实现C数组和C字符串。