Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wisely interpret this compiler warning?

When I executed the code of this question, I got this warning:

warning: format '%d' expects argument of type 'int', but argument 2 has type 'long int' [-Wformat=]
printf("P-Q: %d, P: %d, Q: %d", (p - q), p, q);
             ~^                 ~~~~~~~
             %ld

As a reflex fix, I used %ld to print the subtraction of two pointers. And the compiler agreed.

Fortunately, I saw a comment from another user mentioning that %td should be used, since the result type of the subtraction is ptrdiff_t. This answer confirms this claim.

Now from GCC's header file of stddef.h, I can see that these types are equivalent in this case:

typedef __PTRDIFF_TYPE__ ptrdiff_t;
#define __PTRDIFF_TYPE__ long int

However, I was just going to suggest a wrong (more or less) fix to the OP, with %ld, instead of %td.

Is there a way I could have understood that the compiler warning alone was not enough? Or maybe to wisely have interpreted the warning itself, and not just react.

like image 965
gsamaras Avatar asked Jun 27 '18 08:06

gsamaras


People also ask

What are the warnings did the compiler give you explain the reason for the warnings?

Compiler warnings are messages produced by a compiler regarding program code fragments to be considered by the developer, as they may contain errors. Unlike compilation errors, warnings don't interrupt the compilation process.

How do you treat warning errors?

TreatWarningsAsErrors. The TreatWarningsAsErrors option treats all warnings as errors. You can also use the TreatWarningsAsErrors to set only some warnings as errors. If you turn on TreatWarningsAsErrors, you can use WarningsNotAsErrors to list warnings that shouldn't be treated as errors.

Which option can be used to display compiler warnings?

The warning message for each controllable warning includes the option that controls the warning. That option can then be used with -Werror= and -Wno-error= as described above. (Printing of the option in the warning message can be disabled using the -fno-diagnostics-show-option flag.)


2 Answers

I don't think you can tell. It depends on the intent/caution/smartness of the compiler writer.

Maybe he decided he would always support %ld where %td is expected, or maybe he was just unaware/unable/unwilling to give a more detailed/proper message. In case of doubt, your last resort is the standard.

This doesn't seem to be a portable construct and for "orthodoxy" you should support both format specifiers.

like image 174
Yves Daoust Avatar answered Oct 22 '22 22:10

Yves Daoust


The key here is: don't do any form of arithmetic inside printf in the first place. Separate algorithm from GUI.

Code such as printf("%d", p - q) is very dangerous, not just because you might get the types wrong logically, but also since C might "do you a favour" and silently change the types through implicit type promotion. Examples.

In addition, most compilers don't warn for wrong format specifiers. This is a relatively new thing in the history of C, since compilers aren't required to show a diagnostic message here. It is just a bonus feature of gcc.

How to avoid bugs? These functions are inherently dangerous - that's just how it is and everyone knows it. Probably printf & scanf family of functions are the most harmful functions ever written in the history of programming, in terms of total bug cost caused to mankind. So what you should do to:

  • Avoid stdio.h if possible and keep it away from production-quality code. Portability is not always more important than robust code - sometimes it is preferable to use the raw console API. Avoid variable argument list functions in general.
  • If not possible to avoid, wrap the "GUI" part of stdio.h inside a separate file, which you should be doing anyway. Don't mix printing/input with algorithms. Make an interface which is using pointers.
  • It is 2018, not 1970: don't write console interfaces in the first place. Ye ye I know... there's lots of old crap still floating around which needs to be maintained. But nowadays, console functions should be used mostly for debugging purposes and for newbies learning C, in which case type safety might not be such a big issue.
like image 40
Lundin Avatar answered Oct 22 '22 22:10

Lundin