2015-11-10 19 views
9

標準のCコンパイラをベースにしたMicrochipのXC32コンパイラを使用しています。C言語で単精度IEEE-754フロートとして32ビット符号なしlongを解釈する

私はRS485ネットワーク上のデバイスから32ビットの値を読み取り、これをDWORDとしてtypedefされた符号なしlongに格納しています。

すなわち

typedef DWORD unsigned long; 

現状では、私はfloatにこの値を型キャストするとき、私が取得値は、基本的にはそれの浮動小数点バージョンの整数表現はなく、適切なIEEE-754解釈フロートです。

すなわち

ここ
DWORD dword_value = readValueOnRS485(); 
float temp = (float)dword_value; 

は、小数点以下が1130807492として表現されるよう0x4366C0C4としてHEX形式で通ってくるでしょうdword_valueはそうフロートに、このの型キャストは、単に私を与え1.130807492 * 10^9または1130807492.0それは私が望むものではありません。

私はそうはっきりとfloatに型キャストすることは私のために動作しません私に230.75299072265625

のfloat値を与えるだろう単精度IEEE-754の表現をしたいです。私はこのフォームを私に変換する方法が必要です。私はXC32ライブラリの中を見渡しましたが、何も見つかりませんでした。

私にこの解釈を適切に行う定義済みの方法を知っている人はいますか?または、私が書くことができるいくつかの提案された方法がありますか?私はこの特定のタスクのために私自身のコードを書くのを避けようとしています.Cが既にこのための関数を持っていれば効率的な解決策が見つからないと心配しています。

興味深いのは正しく230.75として* Iがchar *にこれを行う場合、値はその文字で表現され、次のとおりです。画面に

sprintf(random_char_pointer, "%.2f, dword_value); 

ここで印刷random_char_pointerは私に230.75を与えるので、sprintfのでなければなりません私のための解釈を正しく処理する。したがって私は既にCの中に何かがあると仮定しています。誰も助けることができますか?

+2

'f = *(float *)&uvalue;'(プラス/マイナスアラインメントの考慮) – joop

+0

@joopこれは 'float'へのキャストと同じではありませんか? – Downvoter

+1

いいえ、私はunsigned int *ポインタ*をfloat *ポインタ*にキャストし、逆参照します。 – joop

答えて

7

このようなものを行うために推奨される方法は、労働組合を使用することです:

union { 
    DWORD w; 
    float f; 
} wordfloat; 

wordfloat.w = dword_value; 
temp = wordfloat.f; 

これはISO 9899ごとに何をしたいん:2011§6.5.2.3¶3脚注95:

接尾辞の後に.という演算子が続き、識別子が構造体または共用体のメンバーを指定します。値は指定されたメンバーの値で、95)で、最初の式が左辺値の場合は左辺値になります。最初の式が修飾型を持つ場合、結果は指定されたメンバのタイプの修飾バージョンである を持ちます。

95)ユニオンオブジェクトの内容を読み取るために使用されたメンバが、最後にオブジェクトに値を格納するために使用されたメンバと同じでない場合、値のオブジェクト表現の適切な部分がオブジェクトとして再解釈されます6.2.6に記述されているような新しいタイプの表現(「型打ち」と呼ばれることもある)。これはトラップ表現かもしれません。

+0

ありがとうFUZxxlはこれを試してみようと思います –

+0

私は不思議です、「揮発性」の推薦はどこから来たのですか?この種のデータ再解釈を行う能力は、C言語で(通常の不揮発性の) '共用体 'が存在する主な理由の1つです。 – user4815162342

+1

いいえ、2つのメンバが同じ場所を共有するので、volatileは必要ありません(基本的に無意味です。 IIRC組合は、2人のメンバーが正確に同じ場所を共有することを保証しません(私の簡略化したコメントと同じように、2人のメンバーのアラインメントまたはサイズは依然として異なる可能性があります) – joop

関連する問題