2016-09-26 6 views
1

単純な質問、私たちはC言語キャストvoidのポインタを知られていないデータ型で既知のサイズでキャストできますか?既知のサイズのC言語キャストvoidポインタ

機能assertEqual、それらと同等の値を間接参照し、引数として2つのポインタを取得する必要があります:

は、このような状況を考えてみましょう。もちろん、voidポインタを参照解除することはできませんが、ポインタが指すデータのサイズを知っていればどうなりますか?既知のサイズの不明なデータ型の動的ポインタを作成できますか?この関数は、 のassertEqual(void * expected、void * current、size_t size)のようになります。

+2

逆参照する場合は、タイプを選択する必要があります。平等は「既知の」型に対してのみ定義されます。 –

+0

ほとんどの場合、関数は「ファンクタ」であり、その存在の全体的なポイントは型固有の比較を提供することです。つまり、関数はどの型をキャストするかを知っています。標準関数 'bsearch'がどのように機能しているかを読んでください。すべてが明確になるはずです。 – Lundin

+0

私はポインタのサイズを指すのではなく、あなたが指しているオブジェクトのサイズを意味すると思います。 – Olaf

答えて

3

あなたはunsigned char*に引数をキャストしてから最初のsizeバイト(またはことを行い、より良い使用memcmp)を比較するが、それはあなたが与えられたために複数の表現がある場合にはやりたいということは保証されませんでした(例えば、構造体のパディングを考えると、パディングの内容の違いはおそらく無害ですが、このような方法で検出されます。浮動小数点形式のNaN値などの他の場合があります。最も基本的なタイプ)。

+1

'memcmp'は厳密なエイリアシング規則に違反することはなく、一連の文字比較を行うこととして定義されています –

+0

しかし、構造体の埋め込みはsizeof関数で考慮されています。だから私が宣言している型のsizeofでsize_tを渡すと、大丈夫ですか? –

+1

@PavelParma: 'sizeof'は、単一のフィールドではなく、' struct'の** total **サイズをもたらします。パディングバイトを含みます。単一の種類のパディングビットもあります。バイト配列(つまり文字種の1つ)を除いて、2つのオブジェクトがバイトワイズ比較を使用して等しいことを保証する保証はありません – Olaf

0

既知のサイズの不明なデータ型の動的ポインタを作成できますか?

原則として。いいえ。 voidポインターを型キャストするには、型を知る必要があります。例えばfloatとintは両方とも4バイトのサイズを持ちますが、型は等価ではありません。

ただし、同等のタイプがある場合は、同等のタイプに型キャストすることができます。例えばいくつかのシステムでは、intとlongは両方とも4バイトで等価です。

+0

'float'と' int'のどちらも4バイトのサイズを持つことは保証されていません。 1バイトから任意のサイズを持つことができます。 – Olaf

+0

これは、同じサイズのデータ​​が互換性がないことを示す例です。大部分のシステムでは、floatは4バイトであり、intはほとんどの32ビットシステムでは4バイトです。 –

+0

大部分のシステムには32ビットの 'int'がありません。さらに、もしそれらが32ビットの 'int'を持っていても' sizeof(int) 'は' 1'(byte)を返すことができます。 – Olaf

0

シンプルな質問、私たちはC言語キャストで知られていないデータ型で既知のサイズでポインタをキャストできますか?

いいえすべてのポインタ型は、それが指す特定の型を持っています。これには、void *が含まれ、その参照先のタイプ(void)は、言語によって提供される不完全な型です。 void *には、の変換可能なのすべての他のオブジェクトポインタ型のポインタ型がありますが、未知のデータ型へのポインタなどはありません。

一方、文字タイプ(たとえばchar *,unsigned char *)へのポインタを使用して任意のタイプのオブジェクトにアクセスすることは有効です。その1つの方法は、タイプが文字の配列である左辺値を使用することです。 size配列へのポインタepcp各ポイント:

int assertEqual(void* expected, void* current, size_t size) { 
    unsigned char (*ep)[size] = expected; 
    unsigned char (*cp)[size] = current; 
    // ... 
} 

尖った-するタイプとして可変長配列型を使用する:あなたはとてもよう頼むものに非常に似た何かを得ることができタイプunsigned charの要素。その配列タイプのサイズはsizeです。たとえば、実際にはsizeof(*ep) == sizeが見つかります。つまり、指定されたサイズのオブジェクトへのポインタがあり、それを介してそのオブジェクトのバイトにアクセスすることができます。

しかし、他の人がすでに指摘しているように、あなたが尋ねるものはちょっと無意味です。2バイトのシーケンスを比較したい場合は、それらが表すオブジェクトのタイプを知らずに、memcmp()を使用します。一方、バイトシーケンスの異なる2つのオブジェクトは、同じ型のオブジェクトとして比較されても等しいため、一般的な等価テストとしては安全ではありません。これは、浮動小数点表現が完全にインプリメンテーション依存であるため、多くの整数型がその値に寄与しないパディングビットを持つことが許可されているために発生します。

さらに、structおよびunionタイプには、指定されていない、必ずしも一貫した値ではないパディングバイトを含めることができます。複合型を==演算子と比較することはできませんが、そのようなオブジェクトの表現を構成するバイト配列を比較しても、必ずしもメンバーごとにオブジェクトを比較するのと同じ結果にはなりません。

関連する問題