2013-02-08 25 views
10

一定のフロートを鋳造し、このコードを見てください:は、暗黙的に

#include <stdio.h> 

int main(void) 
{ 
    short s; 
    int i = 65696; 
    float f = 65696.0F; 

    printf("sizeof(short) = %lu\n", sizeof(short)); 

    s = i; 
    printf("s = %hd\n", s); 
    s = f; 
    printf("s = %hd\n", s); 

    s = 65696; 
    printf("s = %hd\n", s); 
    s = 65696.0F; 
    printf("s = %hd\n", s); 

    return 0; 
} 

それのように出力を与えた:それは32767とない160だからこそ、最後の行で

sizeof(short) = 2 
s = 160 
s = 160 
s = 160 
s = 32767 

f = 65696.0F; s = f;s = 65696.0F;の違いは何ですか?

答えて

13

浮動小数点値の整数部分が新しい型で表現できない場合、変換は未定義の動作です。

SHRT_MAXはおそらく32767なので、shortオブジェクトでは65696.0Fの整数部分は表現できません。

+7

+1。具体的には、6.3.1.4/1:* "実浮動型の有限値を_Bool以外の整数型に変換すると、小数部は破棄されます(つまり、値はゼロに切り捨てられます)。部分は整数型で表現することはできませんが、その振る舞いは未定義です)」* – Jon

+0

@Jonなぜ、私は 'f = 65696.0F; s = f'? – rootkea

+3

@rootkeaこれは未定義の動作でもあり、未定義の動作は予期しないことがあります。 – ouah

1

これは「未定義の動作」です。つまり、コンパイラは自由に実行できます。しかし、「定義されていない」とは、「説明できない」という意味ではありません。コンパイラはint値65696に最初fに変換さs = fの場合に実行し、その後オーバーフローと変換するCPU命令があるので、コンパイラはこれを行い160離れるS、に65696を割り当てている何

浮動小数点数を32ビット整数に直接変換しますが、直接16ビット整数には変換しません。

s = 65696.0Fでコンパイラが行うことは簡単です:65696.0が範囲外であるため、 s、これは2^15-1 = 32767になります。

もし、コンパイラが(GCCと-Sスイッチを使用して、例えば)S = Fに対して生成アセンブリコードを読み取る:

movss -4(%rbp), %xmm0  # Load float from memory into register xmm0 
    cvttss2si  %xmm0, %eax # Convert float in xmm0 into signed 32 bit, store in eax 
    movw %ax, -10(%rbp)   # Store lower 16 bits of eax into memory 
    movswl -10(%rbp), %eax  # Load those 16 bits into eax, with sign extend 

最後の命令が、この場合にはすべて0に設定すると、%eaxレジスタの上位16ビットを切り詰め。それは、S = 65696.0Fのために生成何

は簡単です:

movw $32767, -10(%rbp)  # Store the lower 16 bits of 32767 into memory 
    movswl -10(%rbp), %eax  # Load those 16 bits into eax, with sign extend 
関連する問題