2017-01-29 12 views
0

3ワードの 'データ'を保持できるc構造体を作成したいとします。ダブルまたはロングまたは他のデータを格納するCデータ型

struct _Obj { 
    ??? a; 
    ??? b; 
    ??? c; 
} 
typedef struct _Obj Obj; 

しかし、さまざまなタイプのデータをa、b、cに保存し、必要に応じてキャストできたいと考えています。

たとえば、 'a'は長い場合もありますが、それ以外の場合は倍精度で、さらに別の場合はポインタです。実行時私はそれらに格納されているものを知っているので、必要に応じて時刻を(即座に)データ型にキャストできるようにしたいと考えています。

Obj obj; 
long a = 893; 
obj.a = a; 
double b = 3.14159; 
obj.b = b; 

long newA = (long)obj.a; 
double newB = (double)obj.b; 

基本的には、いくつかのビットを保存しておき、特定の方法で後で解釈できるようにしたいだけです。これはどうすればいいですか?

+2

構造体内で、サポートしたいすべてのデータ型を持つ共用体を使用できます。 –

+1

私はちょうど適切なサイズの 'char'配列を作るか、' union'と言うでしょう。 – HolyBlackCat

+0

@HolyBlackCat私は 'char'配列を使っていません。これは事実上型の安全性を提供せず、慎重な使用なしに厳密なエイリアシングのルールに違反する可能性があります。 – Downvoter

答えて

1

は、労働組合を使用します。

union { 
    long integer; 
    double floating_point; 
    void *pointer; 
} obj; 

あなたはここにキャストする必要はありません、それはより多くのタイプセーフなキャストよりもです。さらに、キャストはランタイムノーオペレーション(リトルエンディアンではない、おそらくそうでない場合はそうではない)であるとは限りません。したがって、キャストオーバーヘッドをゼロにしたい場合は、組合が最善の策です。

コンパイル時に型を決定したい場合は、C11から_Generic featureもあります。

+0

ありがとうございます。正確には、私が探していたもので、とても役に立ちました。 (Stamatic LiatsosとHolyBlackCatにも感謝します) – aepryus

0

Cでは、ビットの再解釈が可能です。

データのバイナリ形式を定義して抽出するだけです。あなたは浮動小数点型を移植可能にすることができますが、これはおそらくここでは過剰です。おそらく、我々が必要とする最も長いデータは80ビットの倍数であると言えるでしょう。したがって、データがどのようなタイプであるかを言うのに、30バイトで十分であり、さらに2バイトが必要です。だから32バイトは2つの数の素敵な丸めの力です。

+0

Cは型安全のためのより良い機能を持っています。 C *はデータの再解釈を可能にしますが、(ab)使用する必要はありません。 C++は、理由のためにCスタイルのキャスティングに代わる他のキャストメカニズムを導入しました。また、適切な注意を払わなければ、厳密なエイリアシングに関する問題が発生する可能性があります。 – Downvoter

+0

型の安全性は非常に過大評価されています。現在の言語がそれを持っている理由は、コンパイラにとっては簡単です。ビット単位のプログラミングでは、ビットが何であり、どのような意味を持ち、移植性が高く、シンプルであり、型システムが変更された場合には壊れず、安全です。誤った形式のビットバッファを解釈すると、最初のテストのバグ。 –

+0

私はここで深く討論に入りたいとは思わないが、私はあなたのことを知りません。 Cは、実装定義、未定義、および不特定の表現と動作を持つ標準型を提供します。これらの型は、Cコードが記述された抽象マシンによって直接定義されるため、移植性があります。また、Cコンパイラは、型および共用体について知っていて、それらのプロパティをエミュレートしています。提案されたソリューションは実行時オーバーヘッドを引き起こす可能性があります。最後に、特定のABIに対してプログラミングしている場合は、特定のアーキテクチャ - 正しいかもしれません。しかし、それがC言語なら、私は同意しない。 – Downvoter

関連する問題