0

私はシステムを開発しています(仮想マシン?これを呼び出す方法がわからない)すべてのデータ構造が配列(または構造体)であり、先頭に3つの整数フィールドがあります(これはバイトをパディングせずに次々と先頭にある必要があります)およびnジェネリック ポインター。私はこれについて多くのことを考えましたが、明確な解決策を見つけるのは難しいようです.

以下は私の最初の試みです。

void **a = malloc(SOME_SIZE);
a[0] = (void *)1;
a[1] = (void *)0;
a[2] = (void *)1;
a[3] = malloc(SOME_SIZE); a[4] = malloc(SOME_SIZE); //and so on...

void *ここでは、整数へのキャストが安全かどうかわかりませんでした。少し勉強した後、次のようにコードを変更しました。

void **a = malloc(SOME_SIZE);
*(uintptr_t *)a = 1;
*((uintptr_t *)a + 1) = 0;
*((uintptr_t *)a + 2) = 1;
a[3] = malloc(SOME_SIZE); a[4] = malloc(SOME_SIZE); //and so on...

しかし、一部のプラットフォームでsizeof(void *)sizeof(uintptr_t). そこで、これを構造体に変更することにしました。

typedef struct data {
    size_t counts[3]; //padding bytes are okay after this line
    void *members[]; //flexible array member
} *data;

data a = malloc(sizeof(*a) + SOME_SIZE);
a->counts[0] = 1;
a->counts[1] = 0;
a->counts[2] = 1;
a->members[0] = malloc(SOME_SIZE); a->members[1] = malloc(SOME_SIZE); //and so on...

ここで、C には 100% 移植可能なジェネリック ポインターがないという問題を発見しましたが、その解決策を見つけることができないので、いくつかの異なるポインター サイズを持ついくつかの奇妙なプラットフォームを無視させてください。

a が任意のオブジェクトへのポインターを格納できることを考えると、void *私の最後の解決策は私の目的を満たしていますか? 私は柔軟な配列メンバーにあまり慣れていないので、間違いを犯した可能性があります。または、まだ見落としている点があるかもしれません。

どんな助けでも感謝します。

4

2 に答える 2

0

unionどれが整数でどれがポインタであるかを知る何らかの手段があると仮定すると、整数とポインタを組み合わせた a を合法的に使用できます。問題の整数型にパディング ビットまたはトラップ表現がないシステムでは、ポインタを格納してから整数を読み戻すと、(未定義の動作を引き起こすのではなく) 常に値が生成されますが、問題の整数の値を考慮する必要があります。無意味。たまたま整数型が だったとしてもuintptr_t、型パニングがポインター型と整数型の間の変換の正当な手段になるという保証はないと思います。

整数値を格納してからポインターを読み取ることは、確かに未定義の整数値の動作であり、正当なポインターを読み取ることによって読み取られるものではありませんでした。正当なポインタを型パニングして得られたがある場合uintptr_t、型パニングを使用してその値をポインタに戻すことはおそらくうまくいくでしょうが、それが指定されているかどうかはわかりません。uintptr_tそのような整数をポインター型にキャストすることや、キャストによって取得された a に対して型のパニングを使用できることは期待できません。

于 2015-03-30T18:31:53.317 に答える