2

I have been working on a program which contains code of the following nature.

printf("%lld",somelonglongint)

I am however working on a sparc platform where long long is 64 bit and int and long int are 32 bit even on 64 bit builds. If by mistake a line of code creeps in that reads

printf("%d",somelonglongint)

There is no compiler warning even with -Wall, nothing, but this code will cause the program to print nonsense, or often cause the program to seg fault. Is there any way of forcing gcc to at least warn on this, and preferably error since the result is catastrophic

camelccc
  • 2,847
  • 8
  • 26
  • 52
  • Hmm, if no answer, then consider using preprocessor macros to define your formatting, so that `lld`, etc are declared #ifdef SPARK #define LONG_LONG_FORMAT lld% and use LONG_LONG_FORMAT in printf? – Mawg says reinstate Monica Mar 19 '15 at 16:11
  • In my experience, GCC usually does warn about format string mismatches. I'll check the details later today. Meanwhile, can you update your question to show a complete self contained compilable example? – Keith Thompson Mar 19 '15 at 16:15
  • 1
    This should warn. Please include your entire compiler invocation, as well as the compiler version. (There is an assumption that you are using `gcc` because of the question tag, but it would be worthwhile verifying that. In any case, the version number is important.) – rici Mar 19 '15 at 17:09
  • 1
    With gcc 4.8.2 and no additional command-line options, I get a warning "format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long long int’ [-Wformat=]". Apparently `-Wformat` is enabled by default. It might not be on other versions, but it's likely to be enabled by `-Wextra` or `-Wall`. With gcc 4.2.1 on SPARC/Solaris 9, the warning is not enabled by default, but it is enabled by `-Wall` or `-Wformat`. What does `gcc --version` print? – Keith Thompson Mar 19 '15 at 17:26
  • @Mawg: That's not likely to be helpful. Defining a macro `LONG_LONG_FORMAT` does nothing to prevent using `"%d"` accidentally. gcc predefines `__sparc__` for SPARC (not SPARK) targets. – Keith Thompson Mar 19 '15 at 17:31

2 Answers2

4

That's what happen when undefined behavior comes into play. Using wrong specifier invoke UB.

C11: 7.21.6.1:

If a conversion specification is invalid, the behavior is undefined.282)If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

Compiled it with flag -Wall and GCC gives me the warning

[Warning] format '%d' expects argument of type 'int', but argument 2 has type 'long long int' [-Wformat=]   

On Ubuntu 14.04 compiled it without -Wall:

haccks@haccksbuntu:~/Desktop$ gcc test.c
test.c: In function ‘main’:
test.c:66:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long long int’ [-Wformat=]
printf("%d\n", somelonglongint);
^
Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
2

From man gcc:

-Wformat

Check calls to "printf" and "scanf", etc., to make sure that the arguments supplied have types appropriate to the format string specified, and that the conversions specified in the format string make sense. This includes standard functions, and others specified by format attributes, in the "printf", "scanf", "strftime" and "strfmon" (an X/Open extension, not in the C standard) families (or other target-specific families). Which functions are checked without format attributes having been specified depends on the standard version selected, and such checks of functions without the attribute specified are disabled by -ffreestanding or -fno-builtin.

R Sahu
  • 204,454
  • 14
  • 159
  • 270