30

I searched around a little bit for information on this but didn't find anything satisfactory. Is there some special behavior to the function call

sprintf(someString, "");

that explains why this is warning (on gcc with -Wall)? I only managed to find that the C standard allows zero-length format strings.

I tried the following example

#include <stdio.h>

int main()
{
    char str[2] = {'a', 'a'};
    sprintf(str, "");
    printf("\'%c\'\'%c\'\n", str[0], str[1]);
    return 0;
}

which prints out

'''a'

which is exactly what I expected to see. So, why the warning?

SirGuy
  • 10,660
  • 2
  • 36
  • 66

3 Answers3

29

The fact that GCC issues a warning usually has nothing to do with whether the construct is legal C, but whether the GCC developers consider it either a likely indication that you meant something other than what you write, or just bad style. Here are some examples:

  • if (x = 0) — you almost surely meant if (x == 0).
  • printf(str) — you almost surely meant either fputs(str, stdout) or printf("%s", str); as written, the code is very dangerous.
  • if (foo == bar & MASK) — you almost surely meant if (foo == (bar & MASK)).

etc.

In your case, I think GCC is questioning why you're calling sprintf(String, "") to do the equivalent of String[0]=0; (the latter is much shorter, faster, and clearer).

dgw
  • 485
  • 1
  • 4
  • 18
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 2
    I agree that would be better, I just don't know if there is more reason than that for considering it a warning. I'm certainly no authority but I didn't think that this particular offense to reasonable programming would have been considered warning-worthy – SirGuy Mar 29 '12 at 14:25
  • 3
    I agree, but GCC does a lot more annoying things with warnings. This is definitely a lesser offense. A bigger one is giving warnings on unused function arguments, which is *inevitable* whenever you're using function pointers that must conform to a particular signature. – R.. GitHub STOP HELPING ICE Mar 29 '12 at 14:46
  • Huh, I've never had that warning come up before, and I have had that situation come up – SirGuy Mar 29 '12 at 14:50
  • They might have fixed it. It used to happen all the time with gcc 2.x and 3.x and `-Wall`. – R.. GitHub STOP HELPING ICE Mar 30 '12 at 00:02
  • 1
    @R just don't name the function parameters and everything is fine: `int op(int a, int) { return -a; }`: no warning for unused second parameter. – YSC Feb 15 '17 at 15:59
  • 1
  • 1
    If they worry about efficiency they could just generate `String[0]=0;` instead of reporting doubtful warning. And also I consider `sprintf(String, "")` to be more clear since it better expresses an idea "make string empty" than `String[0]=0;` which just means "make the first byte of string zero". – anton_rh May 04 '17 at 08:19
  • 3
    While the warning is useful on literal `printf` and `sprintf` calls, it is unfortunate that the same warning applies to any user-defined function that uses the "looks like printf" attribute. Such user-defined functions can have other effects (e.g. printing a prefix, or terminating) which are useful even when the string is empty. – Kerrek SB Oct 10 '18 at 17:34
8

You're getting the warning because gcc knows that the second argument to sprintf() should be a non-empty string, typically one with various format specifications — a functionally equivalent and "more legal" call to the one you're doing in your code would be sprintf(str, "%s", ""). Also, there's almost always one to N additional arguments, enough to fulfill the format specifications. As you're using it here, you're using it as a kind of strcpy(), which, while technically valid, is a very odd way to use the standard library.

Andrew Beals
  • 1,177
  • 8
  • 18
4

It's simply a warning by GCC. If you wish to suppress it for one part of your application, you can do the following:

#pragma GCC diagnostic ignored "-Wformat-zero-length"
int main()
{
     // code that produces a warning
}
#pragma GCC diagnostic warning "-Wformat-zero-length"
Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
  • 3
    I know I can get rid of it, I was wondering why it was there to begin with – SirGuy Mar 29 '12 at 14:38
  • 10
    I think it's just a nonsensical, harmful warning. It could definitely bite code where the format string is either zero length or nontrivial depending on a preprocessor macro's definition/value, and such code seems perfectly reasonable. – R.. GitHub STOP HELPING ICE Mar 31 '12 at 01:32
  • 3
    It's _not_ harmful. It's just letting you know there's something questionable about your code, that you _might_ have made a mistake. Although `sprintf (str, "");` is legal, it's a rather round-about way of making _str_ a zero-length string, and could indicate a logical error in your code. It's not forbidden; just brought to your attention. – Phil Perry Dec 20 '13 at 21:35
  • 4
    @Phil, it's harmful because false positives make identifying true positive warnings more difficult. Most/all of -Wall is legitimate stuff you want to fix, so this hurts that. – Conrad Meyer Apr 19 '19 at 19:24
  • This warning makes it hard to call an exposed `__attribute__((format(printf(...))))` library setter function to set an unexposed string buffer to the empty string in `-Werror` code (e.g. `User_details_set(&user, "");`. – yyny Jul 31 '20 at 13:30