sprintf()是否需要格式说明符才能正常工作?

时间:2016-02-27 21:02:10

标签: c format-specifiers

我已阅读帖子 sprintf format specifier replace by nothing ,以及其他相关信息,但未详细说明。

直到今天,我从未见过sprintf只使用了2个参数 我的系统用于sprintf()的原型是:

int sprintf (char Target_String[], const char Format_String[], ...);

在处理一些遗留代码时,我遇到了这个问题:(简化说明)

char toStr[30];
char fromStr[]={"this is the in string"};
sprintf(toStr, fromStr);

我对原型的解释是第二个参数应该由const char[]组成,并接受标准的ansi C格式说明符such as these

但上面的例子似乎与字符串fromStr作为第二个参数一样正常 是纯粹通过未定义的行为这是否有效?或者这种用法完全合法?

我使用C99编译器在Windows 7上工作。

6 个答案:

答案 0 :(得分:2)

完全合法。可变参数是可选的。

在这种情况下,printf用作strcpy,但为%说明符解析fmt字符串。

我写sprintf(toStr,"%s",fromStr);所以它不必解析那个长字符串。

答案 1 :(得分:1)

您正在观察的行为是正确的,格式字符串不需要具有任何转换说明符。在这种情况下,由...表示的可变长度参数列表的长度为零。这是完全合法的,虽然它的效率肯定低于等效的

strcpy(toStr, fromStr);

答案 2 :(得分:1)

这是完全合法的代码,但

  1. 如果您只想复制字符串,请改用strcpy()
  2. 如果您正在使用用户输入,则可能会使自己容易受到format string attack
  3. 的攻击

答案 3 :(得分:1)

sprintf的概要是:

int sprintf(char *str, const char *format, ...);

这意味着2个参数是合法的选择。

答案 4 :(得分:1)

它起作用,因为你没有其他参数(即没有控制格式%)来打印。

与没有第二个参数的printf没有区别:

int printf ( const char * format, ... );

如果您没有任何第二个参数,它也可以使用:

printf(fromStr);

答案 5 :(得分:1)

  

第二个参数应该由const char[]

组成

函数参数的const说明符保证函数不会更改该参数的值(假设它可以更改它,这是数组的情况,因为它们通过地址传递给函数)。它不需要在实际调用中使用const值。

您发布的代码不使用const字符串作为sprintf()的第二个参数,但是从非const到const的转换是隐式的;没有必要担心。

  

接受标准的ansi C格式说明符

“接受”并不意味着“要求”。您指定的格式字符串不包含任何格式说明符。因此,仅使用2个参数调用该函数(没有要格式化的值)。无论如何,sprinf()将忽略第三个参数,许多现代编译器会发出警告。

更新:我不想开始讨论哪些编译器是现代的,哪些不是。

碰巧我在OSX 10.11上使用默认编译器,这就是它输出的内容:

axiac: ~/test$ cc -v
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.3.0
Thread model: posix
axiac: ~/test$ cc -o 1 1.c
1.c:8:25: warning: data argument not used by format string [-Wformat-extra-args]
    sprintf(x, "abc\n", n);
               ~~~~~~~  ^