5

こんにちは、私は16ビットC環境で作業しており、浮動小数点値を整数値などのビットシーケンスに変換したいと考えています。これを達成する方法を私が知っている方法は複数あります。1つは組合を利用する方法です。そのような:

union ConvertFloatToInt
{  
   float input;  
   unsigned long  output;  
};

これは、同じメモリ領域を読み取り、それを異なる方法で解釈することにより、浮動値を長い値に「変換」します。

union ConvertFloatToInt x;
x.input = 20.00;

結果

x.output = 0x41A00000;

他のメソッドはvoidポインタキャストです...

float input = 40.00;
unsigned long output;
void* ptr;
ptr = &input;
output = *(unsigned long*) ptr;

結果

output = 0x42200000;

これは私がやろうとしていることのアイデアですが、実行時ではなくビルド中にコンパイラに変換を実行してもらいたいです。

変換された浮動データを定数(const)unsignedlongに挿入する必要があります。

float値をvoidに変換し、次にvoidをunsignedlongに変換しようと考えていました。このようなもの:(そして、はい、これは正しくありません、あなたはボイドにキャストすることはできません)

const unsigned long FloatValue = (unsigned long) ((void) ((float) 20.654));

これを行う方法はありますか?私はおそらくvoidポインターで何かを考えていましたが、私が知っているすべてのvoidポインターには変数が必要であり、変数はconst値の割り当てに使用されない場合があります。

編集

私はC90コンパイラを使用しています。質問はファイルスコープを対象としています。

結論

結論は、ブロックスコープで作業する場合を除いて、この質問に対する実際の解決策はないということでした。複数の回答がありましたので、よろしくお願いします。

私の解決策

これは良い解決策ではありませんが、私の問題は解決しますが、これが多くの人々に役立つとは思いません。デモンストレーション用の小さなプログラムを作成しました。これは私のプロジェクトコードではなく、私のプロジェクトで使用されているコンパイラでもありません(誰かがこれはC90コンパイラではないと言う前に)

デモンストレーションで使用されたコンパイラ:gcc(Ubuntu / Linaro 4.6.3-1ubuntu5)4.6.3

typedef union
{
            float myfloat;
            unsigned long mylong;
} custom_type;

typedef struct
{
            int a;
            int b;
            custom_type typeA;
            custom_type typeB;
} my_struct;

const my_struct myobj =
{
                            1,2,3.84F,4
};

int main(void)
{
            printf(":: %f\n", myobj.typeA.myfloat);
            printf(":: %ul\n", myobj.typeA.mylong);
            return 0;
}

出力

:: 3.840000
:: 1081459343l

これは少し大雑把ですが、ファイルスコープでは機能します(ただし、警告が生成されます)。

4

5 に答える 5

5

これは、無名共用体を介して型パニングすることで実行できます。

unsigned int i = ((union { float f; unsigned int i; }){5.0}).i;

この初期化子は定数式ではないため、ファイル スコープでは使用できないことに注意してください。

共用体による型パニングは、脚注の標準で許可されるように指定されています。

6.5.2.3 構造体と共用体のメンバー

95) 共用体オブジェクトの内容を読み取るために使用されるメンバーが、オブジェクトに値を格納するために最後に使用されたメンバーと同じでない場合、値のオブジェクト表現の適切な部分は、新しいオブジェクト表現として再解釈されます。 6.2.6 で説明されているタイプ (「タイプパニング」と呼ばれることもあるプロセス)。これはトラップ表現である可能性があります。

実用的な観点から、このメソッドを使用してファイル スコープ定数を初期化することはできませんが、プログラムまたはモジュールの初期化時に値をファイル スコープ変数にロードする初期化関数を作成できます。

標準のセクション 6.2.6 でカバーされているオブジェクト表現は実行時にのみ適用されるため、値をコンパイル時の定数式として計算できる移植可能なメソッドを見つけることはできません。そうしないと、ターゲットの実行環境をパラメータ化するだけでなく、シミュレートするためにクロスコンパイラが必要になります。


補遺: これ有効な C++ であり、union型に名前を付ける必要があるという条件があります。

union u { float f; unsigned int i; };
unsigned int i = u{5.0}.i;

したがって、ハイブリッド C/C++ で記述し、C++ コンパイラでコンパイルする場合は、コンパイル時にキャストを実行できます。

于 2012-08-03T13:30:00.990 に答える
1

これらの浮動小数点数は定数であると想定しているため、必要に応じて出力を生成する、1 回限りの演習として小さなプログラムを作成するだけで済みます。その小さなプログラムから、他のコードにカット アンド ペースト ジョブを実行します。

それらがたくさんある場合は、C 用の適切なファイルを作成するスクリプトを作成するだけではどうですか。

于 2012-08-03T13:13:38.910 に答える
1

C99 複合リテラルを使用できます。

const unsigned long FloatValue =
        *(unsigned long *) &(float) {20.654f};

初期化子は定数式ではないためFloatValue、ブロック スコープでのみ宣言でき、ファイル スコープでは宣言できないことに注意してください。

于 2012-08-03T13:12:32.417 に答える
0

float 定数を定義してからマクロを定義することで、目的を達成できます。

const float _FloatValue = 20.654;
#define FloatValueL *((unsigned long *) &_FloatValue)
于 2012-08-03T16:47:58.683 に答える
0

IEEE 浮動小数点標準についてある程度知っておく必要があります。 http://en.wikipedia.org/wiki/IEEE_floating-point_standard

小数ビットを取得し、指数ビットを取得して、それらを long に処理します。

于 2012-08-03T13:12:48.910 に答える