C関数パラメータタイプアップ


printfの問題を見たことがありますが、面白いですね.記録してください.float value = 1.0;
printf("value_int = %d/n", value);
printf("value_float = %f/n", value);

何を出力すべきですか?一見、この問題は簡単で、浮動小数点1.0のメモリに格納される形式は0 x 3 f 800000です.float型はメモリに4 Byte、int型も4バイト、0 x 3 f 800000の10進数形式をそのまま出力すればいいのではないでしょうか.誰が知っていますか?大きな眼鏡を運転して、情報を印刷します:value_int = 0value_float=1.0どうしたの?gcc-Sのパラメータを用いる.cプログラムが.sのアセンブリ言語プログラム.次のように見えます.flds    -8(%ebp)
fstpl    4(%esp)
movl    $.LC1, (%esp)
call    printf

ここでvalueの値は-8(%ebp)に存在する.LC 1には「value=%d/n」文字列が格納されている.flds命令は、単精度valueの値をFPUのst 7レジスタ(64 bit)に入れることを意味し、このときst 7の値は0 x 3 f 800000000000であり、次にfstpl命令はFPUのレジスタの値を二重精度でスタックし、4(%esp)に格納する.すなわち(%esp+4)の値は0 x 00000000、(%esp+8)の値は0 x 3 f 800000である.printfを呼び出すと、印刷方式が%dであることが指定されるため、printfは(%esp+4)の4バイトのみを読み取り、(%esp+8)の正確な値0 x 3 f 800000を考慮せずに10進数整形--0と解釈する.floatもメモリに4バイトしか残っていないのに、なぜ%fを指定したときにエラーが発生しないのか疑問に思うかもしれません.答えはprintf出力パラメータを%fと指定すると、printfは低アドレスの4 Byteだけではなくメモリに8バイトを読み出すことです.プログラムを書いてテストするとわかります.int main()
{
    int    a=1, b=2, c=3;
    printf("%f, %d/n", a,b,c);
    return 0;
}

出力結果:0.00000,3であることから,%fは実は8 byteを読み出しているが,a,bがfloat型に変換された場合,いずれも値が小さすぎて0.00000として出力される.