Is 'float a = 3.0;' a correct statement?

If I have the following declaration:

float a = 3.0 ;

is that an error? I read in a book that 3.0 is a double value and that I have to specify it as float a = 3.0f. Is it so?


Solution 1:

It is not an error to declare float a = 3.0 : if you do, the compiler will convert the double literal 3.0 to a float for you.


However, you should use the float literals notation in specific scenarios.

  1. For performance reasons:

    Specifically, consider:

    float foo(float x) { return x * 0.42; }
    

    Here the compiler will emit a conversion (that you will pay at runtime) for each returned value. To avoid it you should declare:

    float foo(float x) { return x * 0.42f; } // OK, no conversion required
    
  2. To avoid bugs when comparing results:

    e.g. the following comparison fails :

    float x = 4.2;
    if (x == 4.2)
       std::cout << "oops"; // Not executed!
    

    We can fix it with the float literal notation :

    if (x == 4.2f)
       std::cout << "ok !"; // Executed!
    

    (Note: of course, this is not how you should compare float or double numbers for equality in general)

  3. To call the correct overloaded function (for the same reason):

    Example:

    void foo(float f) { std::cout << "\nfloat"; }
    
    void foo(double d) { std::cout << "\ndouble"; }
    
    int main()
    {       
        foo(42.0);   // calls double overload
        foo(42.0f);  // calls float overload
        return 0;
    }
    
  4. As noted by Cyber, in a type deduction context, it is necessary to help the compiler deduce a float :

    In case of auto :

    auto d = 3;      // int
    auto e = 3.0;    // double
    auto f = 3.0f;   // float
    

    And similarly, in case of template type deduction :

    void foo(float f) { std::cout << "\nfloat"; }
    
    void foo(double d) { std::cout << "\ndouble"; }
    
    template<typename T>
    void bar(T t)
    {
          foo(t);
    }
    
    int main()
    {   
        bar(42.0);   // Deduce double
        bar(42.0f);  // Deduce float
    
        return 0;
    }
    

Live demo

Solution 2:

The compiler will turn any of the following literals into floats, because you declared the variable as a float.

float a = 3;     // converted to float
float b = 3.0;   // converted to float
float c = 3.0f;  // float

It would matter is if you used auto (or other type deducting methods), for example:

auto d = 3;      // int
auto e = 3.0;    // double
auto f = 3.0f;   // float