Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Must I initialize floats using 0.f?

When I initialize float variables in my program, I commonly have vectors like:

Vector forward(0.f,0.f,-1.f),right(1.f,0.f,0.f),up(0.f,1.f,0.f)

(Vectors are just 3 floats like struct Vector{ float x,y,z; };)

This looks much easier to read as:

Vector forward(0,0,-1),right(1,0,0),up(0,1,0)

Must I initialize my float variables using floats? Am I losing anything or incurring some kind of penalty when I use integers (or doubles) to initialize a float?

like image 569
bobobobo Avatar asked Sep 28 '12 09:09

bobobobo


2 Answers

There's no semantic difference between the two. Depending on some compilers, it is possible for extra code to be generated, though. See also this and this SO questions of the same topic.

I can confirm that gcc generates the same code for all variants of

int main()
{
    float a = 0.0f; /* or 0 or 0.0 */
    return 0;
}

and that this code is

    .file   "1.c"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $0x00000000, %eax
    movl    %eax, -4(%rbp)
    movl    $0, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
    .section    .note.GNU-stack,"",@progbits

The relevant line is

    movl    $0x00000000, %eax

Changing a to 0.1 (or 0.1f) changes the line to

    movl    $0x3dcccccd, %eax

It seems that gcc is able to deduce the correct constant and doesn't generate extra code.

like image 69
Mihai Maruseac Avatar answered Oct 21 '22 01:10

Mihai Maruseac


For a single literal constant, it shouldn't matter. In the context of an initializer, a constant of any numeric type will be implicitly converted to the type of the object being initialized. This is guaranteed by the language standard. So all of these:

float x = 0;
float x = 0.0;
float x = 0.0f;
float x = 0.0L;   // converted from long double to float

are equally valid and result in the same value being stored in x.

A literal constant in a more complex expression can have surprising results, though.

In most cases, each expression is evaluated by itself, regardless of the context in which it appears. Any implicit conversion is applied after the subexpression has been evaluated.

So if you write:

float x = 1 / 2;

the expression 1 / 2 will be evaluated as an int, yielding 0, which is then converted to float. It will setxto0.0f, not to0.5f`.

I think you should be safe using unsuffixed floating-point constants (which are of type double).

Incidentally, you might consider using double rather than float in your program. double, as I mentioned, is the type of an unsuffixed floating-point constant, and can be thought of in some sense as the "default" floating-point type. It usually has more range and precision than float, and there's typically not much difference in performance.

like image 39
Keith Thompson Avatar answered Oct 21 '22 02:10

Keith Thompson