Domanda

A while ago I was hunting for bug a that was causing wrong numeric data being written to log files. Turned out that the problem was that code equivalent to the following:

int main(void) {
    struct {
        double a;
        int b;
    } s = { 1, 2 };

    printf("%lf\n", s.a);
    printf("%lf\n", s.b);
}

was outputting

1.000000
1.000000

Apparently printf was expecting the second value in floating point registers, not in the stack. To prevent such mistakes from happening in the future, should one cast all printf parameters to be sure that they really are of the expected type?

È stato utile?

Soluzione 2

should one cast all printf parameters to be sure that they really are of the expected type?

Not generally. You should use the correct combination of format specifier and argument type for each argument you are passing. Of course, if you have an argument that is the "wrong type" (e.g. an int that you want to print using a floating point format specifier) then it needs to be converted in some way, which would typically mean a cast. But scattering a load of casts all over your printf lines "just in case" is not the right solution here.

Note that there is no requirement for the compiler to "understand" the format string of printf (or scanf or strftime, etc), so the compiler is just obliged to pass arguments according to a set list of restrictions (float is converted to double, short integers (char, short) are converted to int, and a few other things like that). Then it comes down to the printf to sort out what you have. And of course, if you don't have the right format specification for the argument, then printf may indeed look in the wrong place for the arguments.

So, in summary, you need to match the argument type for printf. If that means that you occasionally need a cast, then yes, use a cast. But it shouldn't be a "regular thing".

Altri suggerimenti

According to C99 standard. Mismatch in format specifier and datatype of actual data to be printed is Undefined behavior

Here b is and int so if you give "%d" in 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

should one cast all printf parameters to be sure that they really are of the expected type?

If the types are different than what would be expected, yes. If you enable warnings for your compiler, it will tell you this.

I suspect you are acting on the belief that the template specifiers for printf indicate what style you would like a value displayed as. This is partially true, and (via casting) can be made to work with the primary purpose, but the primary purpose is to indicate to printf what kind of value is being considered.

So, if you have an integer type, you might use %d, but not %f, because %f would be a lie, and lying to a computer is a tricky business. If the purpose of the %f is because you want the value printed with decimal places, then you should cast it; this will convert the integer value into a float properly. (You could also just use %d.000000 since an integer has no fraction anyway).

Otherwise, you should just use a specifier appropriate to the type.

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

Instead of cast all printf parameters to be sure that they really are of the expected type you should make sure that whatever specifier you put in printf is the correct type. You know that s.b is an int so why use %f?

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

Even you don't use Hungarian notation, just use some tag in your variables to deliver the type infor. Then when you type printf("%lf\n", s.n_b);, it's easy to find the trap here.

C type cast has bad side effect in different platforms. They are tricky and sloppy. If there is other way to solve issue, don't use type cast.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top