1

間違った結果を出力しているこのコードがあります。

#include <stdio.h>
#include <string.h>

int main() 
{
  unsigned char bytes[4];
  float flt=0;

  bytes[0]=0xde;
  bytes[1]=0xad;
  bytes[2]=0xbe;
  bytes[3]=0xef;

  memcpy( &flt, bytes, 4);

  printf("bytes 0x%x float %e\n", flt, flt);
  return 0;
}

私が得る出力は

バイト0xc0000000float-2.000001e + 00

私は得ることを期待しています

バイト0xdeadbeeffloat-6.2598534e + 18

エンディアンが異なる可能性があると指摘されたように、#1を編集すると、次のようになります。

バイト0xefbeaddefloat-1.1802469e + 29

私が理解していないのは、floatからunsigned intへのキャストで0xc0000000になります(同じprintfステートメントのfloatは-2.0000であり、コンパイラの最適化に起因します)

これは以前は別のコンピューターで機能していました。アーキテクチャの変更である可能性があります。

4

5 に答える 5

8

memcpyの問題ではありません。

  1. floatdoubleprintfを渡すと常に に変換される...ため、ほとんどの Intel アーキテクチャでは 4 バイトを取得できません。
  2. このコードで期待するとき0xdeadbeefは、アーキテクチャが BIG エンディアンであると想定します。Intel x86 など、多くのリトル エンディアン アーキテクチャがあります。
于 2009-05-09T08:33:57.557 に答える
6

printf()のような変数パラメーター関数に渡されると、floatがdoubleにプロモートされることをご存知ですか?だからあなたが言うとき:

printf("bytes 0x%x float %e\n", flt, flt);

あなたは実際には2つの8バイト値を2つの4バイト値のように扱い、未定義の動作を与えようとしています(私は信じています)。

于 2009-05-09T08:22:07.600 に答える
2

printf の "%x" は unsigned int を想定しています。自動的に変換されるフロートを与えていますが、それはあなたが望むものではありません。次のようなことをしたい:

printf("bytes 0x%x float %e\n", *((unsigned int *)&flt), flt);

ああ、他の誰かが指摘したように、x86 を使用している場合、0xdeadbeef は表示されず、0xefbeadde のようになります。

于 2009-05-09T08:40:41.377 に答える
1

これがより良いかどうかを確認してください:

printf("bytes 0x%x float %e\n", *(int *)&flt, flt);
于 2009-05-09T08:40:43.000 に答える
1

パラメーターの昇格を確認するには、宣言を float から double に変更します。私のマシンでは、次のように出力されます。

bytes 0xefbeadde float -1.860545e+230

0xefbeadde はデッドビーフのビッグエンディアンです。double の最後の 4 バイトは未定義であるため、float の後に表示される数値は異なります。

別のコンピューターで動作するとおっしゃいましたが、それはどのようなコンピューターでしたか? sizeof(float) == sizeof(double) :) スモール エンディアンである必要があります。

于 2009-05-09T08:58:18.573 に答える