11

I was wondering how can a function issue a compile-time warning?

This came to my mind because when we supply wrong format specifier in the first argument of printf (scanf) for the variable matched with that type specifier and compile with gcc with -Wall option on, compiler issues a warning.

Now, printf and scanf are regularly implemented variadic functions as I understand and I dont know any way to check the value of the string at the compile-time, let alone issue a warning if something doesnt match.

Can someone explain me how I get compiler warning then?

user1635881
  • 239
  • 3
  • 11
  • Doesn't the compiler know (a) what format string you've given it (and thus can know the format specifiers, and (b) what data types you've passed to the `printf` albeit there are a variable number? So it can easily tell if you have mismatched data and specifiers. – lurker Oct 24 '15 at 18:30
  • 1
    Yup, then it would be possible to do so with any other function it sees. Printf is just another stdio.h function that should be no different than any mine or yours function. – user1635881 Oct 24 '15 at 18:35
  • OK, sorry, your question wasn't clear. I thought you were asking how it was possible for `printf` and `scanf`. You're wanting to get a warning on a function you write yourself? – lurker Oct 24 '15 at 18:37
  • 1
    Well, I was wondering if it is possible :) – user1635881 Oct 24 '15 at 18:41
  • 1
    Ah, I see. Good question! (+1) – lurker Oct 24 '15 at 18:43
  • Thank you, though it is not answered completely :) – user1635881 Oct 24 '15 at 18:50
  • 1
    @user1635881 "Printf is just another stdio.h function that should be no different than any mine or yours function." -- not quite, `printf()` is specified in the C standard, so it *is* part of the language. –  Oct 24 '15 at 19:01

3 Answers3

12

Warnings are implementation (i.e. compiler & C standard library) specific. You could have a compiler giving very few warnings (look into tinycc...), or even none...

I'm focusing on a recent GCC (e.g. 4.9 or 10...) on Linux.

You are getting such warnings, because printf is declared with the appropriate __attribute__ (see GCC function attributes)

(With GCC you can likewise declare your own printf-like functions with the format attribute...)

BTW, a standard conforming compiler is free to implement very specially the <stdio.h> header. So it could process #include <stdio.h> without reading any header file but by changing its internal state.

And you could even add your own function attributes, e.g. by customizing your GCC with your GCC plugin

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • So compiler still has a special treatment for printf-like functions since it examines the format string at compile time. I can see thst there is warning attribute, but still it is generated at compile time (when function with the attribute is called after dead code elimination) – user1635881 Oct 24 '15 at 18:39
  • 3
    @user1635881 yes -- and thinking about that, it's really a sensible thing to do: `printf()` is not only part of the standard, it also has a well-known contract for the *format string* (even used in quite some custom functions) than can undergo *some* static diagnostics, so why not offer that debugging aid to the programmer. –  Oct 24 '15 at 18:59
  • I agree but, that could open up Pandora's box of sorts. You see, there may be another functions for which compiler may add a static analysis and you may become accustomed to that, but when you turn to another compiler that feature might be missing. So maybe it is the best to standardize this such as this? – user1635881 Oct 24 '15 at 19:13
  • No, because warnings are not even known to the standard. It is an implementation specific thing. – Basile Starynkevitch Oct 25 '15 at 07:58
6

How can printf issue a compiler warning?

Some compilers analyze the format and other arguments type of printf() and scanf() at compile time.

printf("%ld", 123);  // type mis-match  `long` vs. `int`
int x;
printf("%ld", &x);  // type mis-match 'long *` vs. `int *`

Yet if the format is computed, then that check does not happen as it is a run-time issue.

const char *format = foo();
printf(format, 123);  // mis-match? unknowable.
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

You're absolutely right that it's unusual for a compiler to warn about specific functions. Warnings about printf (and scanf, and related) format specifiers are quite unusual -- but then, these functions are quite unusual in the first place. As other answers have explained, it's at least possible for a compiler to "know" about certain functions and to perform special, extra, compile-time checks like this -- and given that printf and scanf and friends are simultaneously very unusual and very popular, it's quite appropriate for compilers to be doing this extra checking, unusual though it is.

Once upon a time (I'm talking about the pre-ANSI, K&R days here), C programmers knew they had to be careful about calling functions with the correct number and type of arguments. (In those days, the only way to automatically check that was to use lint, which some programmers did but many programmers didn't.) And if you were used to being careful, it was easy to be careful about printf and friends, also.

Today, though, it's a different story. ANSI C function prototypes have been in use for a generation. Most programmers today implicitly expect a compiler to automatically convert the types of function arguments, and to complain about incompatible mismatches. (As an example of the way things have changed: in the old days, calling sqrt(144) was an error that quietly gave mysterious results, but today it's fine.)

So today, I have a great deal of sympathy for programmers who are learning C, and are baffled by printf. If you're completely used to the protections afforded to you by function prototypes, it's a pretty great mystery why

int i = 3;
float f = 4.5;
printf("i as a float is %f, f as an int is %d\n", i, f);

doesn't work. Unlike the old days, I suspect, it is very hard to remember that, when you call printf (but pretty much only when you call printf), it's your job to get all the types right, because the compiler won't insert any implicit conversions.

The bottom line is that, today, not only is it possible for a compiler to warn about mismatches in calls to printf and the like, I believe it's pretty much a moral imperative. When we introduced function prototypes, we promised programmers type safety for function arguments, so it's really not fair to quietly withdraw that promise when it comes to printf.

[P.S. Yes, of course I know why function prototypes can't promise complete type safety for varargs functions like printf. But that's got nothing to do with my argument here. Also, yeah, I know, life isn't fair, so call me an old softie with my highfalutin talk of "moral imperatives". :-) ]

Steve Summit
  • 45,437
  • 7
  • 70
  • 103