简体   繁体   中英

Does sprintf() require format specifiers to work properly?

I have read the post sprintf format specifier replace by nothing , and others related, but have not seen this addressed specifically.

Until today, I have never seen sprintf used with only 2 arguments.
The prototype my system uses for sprintf() is:

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

While working with some legacy code I ran across this: (simplified for illustration)

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

My interpretation of the prototype is that the second argument should be comprised of a const char[] , and accepting standard ansi C format specifiers such as these .

But the above example seems to work just fine with the string fromStr as the 2nd argument.
Is it purely by undefined behavior that this works?, or is this usage perfectly legal?

I a working on Windows 7, using a C99 compiler.

Perfectly legal. The variadic arguments are optional.

In this case the printf serves as strcpy but parses the fmt string for % specifiers.

I'd write sprintf(toStr,"%s",fromStr); so it doesn't have to parse that long string.

The behavior you are observing is correct, a format string is not required to have any conversion specifiers. In this case the variable-length argument list, represented by ... , has length of zero. This is perfectly legal, although it's definitely less efficient than its equivalent

strcpy(toStr, fromStr);

It's perfectly legal code, but

  1. If you just want to copy a string, use strcpy() instead.
  2. If you are working with user input, you could be making yourself vulnerable to a format string attack .

Synopsis for sprintf is:

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

That means 2 arguments are legal option.

It works because you have no further parameter (ie no control format % ) to print.

It's no difference than printf without second parameter:

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

It also works if you don't have any second parameter:

printf(fromStr);

the second argument should be comprised of a const char[]

A const specifier of a function argument guarantees that the function does not change the value of that argument (given it can change it which is the case on arrays because they are passed by address to the function). It does not require that a const value to be used on the actual call.

The code you posted do not use a const string as the second argument to sprintf() but the conversion from non-const to const is implicit; there is no need to worry there.

accepting standard ansi C format specifiers

"accepting" does not mean "requiring". The format string you specified does not contain any format specifier. Accordingly, the function is called with only 2 arguments (no values to format). A third argument would be ignored by sprinf() anyway and many modern compilers would issue an warning about it.


Update : I don't want to start a debate about which compilers are modern and which are not.

It happens that I'm using the default compiler on OSX 10.11 and this what it outputs:

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);
               ~~~~~~~  ^

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM