Why does the variable x of the double type always print the same WRONG value in scientific notation?

Asked

Viewed 224 times

0

In this first example I would like to know why the variable x read in double, when it is formatted by the function "printf()" does not display the value correctly, and every time the value is the same.

#include <stdio.h>

int main(){
    double x;

    scanf("%f", &x);

    printf("%e", x);

    return 0;
}

2) A variable x of the type float, when printed on the screen in the whole format will always give 1?

#include <stdio.h>

int main(){
    float x;

    scanf("%f", &x);

    printf("%d", x);

    return 0;
}

3) Why the variable x of the whole type when printed in double format is 0 ?

#include <stdio.h>

int main(){
    int x;

    scanf("%d", &x);

    printf("%f", x);

    return 0;
}
  • 3

    The scanf for double is not using %f and family, but %lf and family

  • 3

    Over two and three, there is no coercion of type, neither from floating point to integer nor the other way around, so the value will be quite chaotic, because the printf will interpret the past bytes as being of another type

  • 1

    And to complement what @Jeffersonquesado said a double/float has the exponent stored in the bits of higher weight (usually 8) soon and most of the values are quantified to zero because they do not generate information until these bits

1 answer

1


So - as it is in the comments: these functions printf and scanf has not how to know what type of argument you are passing to them from the declared type of the variable.

They just "guess" what kind of data was passed, or what they should copy to the variable (in the case of scanf), from precisely the formatting string.

So when you, in case 3, say to the printf that will pass a float type number, it will take the corresponding bytes of the parameter stack and treat them as a double. (See below for a double and not a float). And the internal values of these bytes are very different for a float and an integer of 4 bytes.

The same way for the double, when using the scanf you have to say if the variable you will fill is a "double" or a "float" - the second case uses the formats %f, %e or %g but always fills only 4 bytes in target memory with the bytes corresponding to a float. To the scanf work with a double, it is necessary to use the modifier l in format: %lf, %le, %lg.

What confuses is that the compiler itself, due to the specification of the C language will always turn a float in a double automatically when a variable parameter function is called.

So in fact the %f (and %e) in the printf will always handle doubles (and use 8 bytes of argument stack), even if in your code you write that you are passing a float. (and yes, the codes are therefore different from those used by scanf).

In C it is necessary to understand well how the different types of data are represented in memory, and there can be even an error. For example, if instead of the examples you passed, you tried to print a variable int using the formatting %f, your program could end with a segmentation failure - since the printf will want to consume 8 bytes of argument where there is only 4. In dynamic languages with a higher abstraction level such as Javascript, Python, PHP and Ruby, these exact data conversion problems for your internal representation in general are handled by the language itself. Other static languages like C#, go, Java, etc... will have better mechanisms to detect this type of problem at the time of compilation. But in C, it’s just you and the CPU. :-)

  • Just out of curiosity, if the endianess were distinct, the printfwould continue with the same results?

  • 1

    No. Only when the data is the same size. As in one case the error is in the format string for scanf, for example, 4 different bytes of the double variable will be filled by scanf with %f (instead of right %lf) - and in the prints, the printing of "ints" passing a double would also take 4 different bytes.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.