Should printf parameters always be specified?

Some time ago, I was looking for an error that caused incorrect numerical data being written to log files. It turned out that the problem is that the code is equivalent to the following:

int main(void) { struct { double a; int b; } s = { 1, 2 }; printf("%lf\n", sa); printf("%lf\n", sb); } 

deduced

 1.000000 1.000000 

Apparently printf expecting a second value in floating point registers, not on the stack. To prevent such errors in the future, all printf parameters should be specified to make sure that they really have the expected type?

+4
source share
5 answers

Should all printf parameters be specified to make sure they are of the expected type?

Not at all. You must use the correct combination of format specifier and argument type for each argument you pass. Of course, if you have an argument that is the "wrong type" (for example, the int you want to print using the floating point format specifier), you need to convert it somehow, which usually means throwing. But dispersing the load of drops on all your printf lines “just in case” is not the right solution here.

Please note that the compiler does not require "understanding" the printf format printf (either scanf or strftime , etc.), therefore the compiler is simply obliged to pass arguments in accordance with the specified list of restrictions ( float converted to double , short integers ( char , short ) are converted to int and some other similar things). Then, before printf you can determine what you have. And, of course, if you do not have the correct format specification for the argument, then printf may indeed be in the wrong place for the arguments.

So, in general, you need to match the argument type for printf . If that means you sometimes need a throw, then yes, use a throw. But this should not be a "normal thing."

+2
source

According to the standard C99. Inconsistency with the format specifier and data type of the actual data to be printed, Undefined behavior

Here b is and int if you give "%d" in the second printf() function. It will print the correct value otherwise Behavior is Undefined

From c99

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

+5
source

Should all printf parameters be used to ensure that they really have the expected type?

If the types are different than expected, yes . If you enable warnings for your compiler, this will tell you that.

I suspect you are acting on the belief that the template specifiers for printf indicate in which style you would like to display the value. This is partially true, and (through casting) can be made to work for the main purpose, but the main goal is to tell printf which value is being considered .

So, if you have an integer type, you can use %d , but not %f , because %f will be a lie, and lying to a computer is a complex business. If the goal of %f is that you want the value to be printed in decimal places, you must drop it; this will result in the correct conversion of the integer value to a float. (You can also just use %d.000000 , since the integer has no fraction).

Otherwise, you should just use a qualifier that matches the type.

+2
source

In your code, printf takes the internal binary representation of the integer 2 and treats it like a float.

Instead of cast all printf parameters to be sure that they really are of the expected type you must make sure that any qualifier that you put in printf is the correct type. You know sb is int , so why use %f ?

+1
source

To be honest, if you change the data type from struct {double a; int b; } s = {1, 2}; in struct {double d_a; int n_b; } s = {1, 2};

Even you don’t use Hungarian notation, just use some kind of tag in your variables to deliver type information. Then, when you print printf ("% lf \ n", s.n_b), it is easy to find a trap here.

Type C listing has a bad side effect across platforms. They are complicated and messy. If there is another way to solve the problem, do not use the cast type.

0
source

Source: https://habr.com/ru/post/1499773/


All Articles