我必须使用0.f初始化浮点数吗?

bob*_*obo 9 c++ variables initialization

当我float在程序中初始化变量时,我通常会有以下向量:

Vector forward(0.f,0.f,-1.f),right(1.f,0.f,0.f),up(0.f,1.f,0.f)
Run Code Online (Sandbox Code Playgroud)

(向量只有3个浮点数struct Vector{ float x,y,z; };)

这看起来容易阅读:

Vector forward(0,0,-1),right(1,0,0),up(0,1,0)
Run Code Online (Sandbox Code Playgroud)

我必须float使用floats 初始化我的变量吗?当我使用整数(或doubles)初始化时,我会丢失任何东西或招致某种惩罚float吗?

Mih*_*eac 8

两者之间没有语义差异.但是,根据某些编译器,可能会生成额外的代码.又见同一主题的SO问题.

我可以确认gcc为所有变体生成相同的代码

int main()
{
    float a = 0.0f; /* or 0 or 0.0 */
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

并且这段代码是

    .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
Run Code Online (Sandbox Code Playgroud)

相关的是

    movl    $0x00000000, %eax
Run Code Online (Sandbox Code Playgroud)

更改a0.1(或0.1f)将行更改为

    movl    $0x3dcccccd, %eax
Run Code Online (Sandbox Code Playgroud)

似乎gcc能够推断出正确的常量并且不会生成额外的代码.


Kei*_*son 7

对于单个文字常量,它应该无关紧要。在初始化程序的上下文中,任何数字类型的常量都将隐式转换为正在初始化的对象的类型。这是由语言标准保证的。所以所有这些:

float x = 0;
float x = 0.0;
float x = 0.0f;
float x = 0.0L;   // converted from long double to float
Run Code Online (Sandbox Code Playgroud)

同样有效并导致相同的值存储在x.

但是,更复杂表达式中的文字常量可能会产生令人惊讶的结果。

在大多数情况下,每个表达式都会自行计算,而不管它出现在什么上下文中。在评估子表达式应用任何隐式转换。

所以如果你写:

float x = 1 / 2;
Run Code Online (Sandbox Code Playgroud)

表达式1 / 2将被计算为一个int, yielding 0,然后转换为float. It will setx to0.0f , not to0.5f`。

我认为使用无后缀的浮点常量(类型为double)应该是安全的。

顺便说一句,您可能会考虑使用double而不是float在您的程序中。double,正如我所提到的,是无后缀浮点常量的类型,在某种意义上可以被认为是“默认”浮点类型。它通常比 具有更大的范围和精度float,并且通常在性能上没有太大差异。