0

プログラムで使用される構造は次のとおりです。

struct basic_block
{
  void * aux;

  /* Many other fields,
  which are irrelevant.  */
};

今:

  1. basic_blockプログラムの実行中に のインスタンスがいくつか存在します。
  2. プログラムはステージ/パスで動作し、次々に実行されます。
  3. このauxフィールドはbasic_block、ステージの実行中にステージと特定のデータを格納するためのものであり、ステージ自体によって解放されます (次のステージで再利用できるようになります)。これがvoid *.

私のステージはauxを格納するstructために使用されるため、何かにアクセスするたびに、キャストを行う必要があります。

( (struct a_long_struct_name *) (bb->aux))->foo_field = foo;

さて、私の問題です。このように毎回キャストするのは苦痛であり、より複雑な式の一部であると読みにくいです。私が提案した解決策は次のとおりです。マクロを使用してキャストを行います。

#define MY_DATA(bb) \
  ( (struct a_long_struct_name *) (bb)->aux)

次に、次の方法でデータにアクセスできます。

MY_DATA(bb)->foo_field = foo;

しかし:私はMY_DATA(bb) 自分自身を( a の)L値として使用することはできないmallocので、結局、そのマクロを使用することはあまり良い考えではありません:

/* WRONG! I cannot assign to the result of a cast:  */
MY_DATA(bb) = malloc (sizeof (struct a_long_struct_name));

私の質問:

auxクリーンな方法で参照し、それを L 値として使用できるようにするにはどうすればよいですか。

4

4 に答える 4

2

試す:

#define MY_DATA(bb) \
  ( *(struct a_long_struct_name **) &(bb)->aux)

これによりエイリアシングが導入されるため、マクロの使用に一貫性を持たせる必要があることに注意してください。

于 2012-06-20T15:51:44.577 に答える
2

コードにマクロ呼び出しを散らかす必要はありません。

struct a_long_struct_name* strp = malloc(sizeof *strp);
if (!strp)
    <handle OOM>
bb->aux = strp;
strp->foo_field = foo;
etc.
于 2012-06-20T16:41:15.977 に答える
2

フィールドのアドレスをキャストしてstruct a_long_struct_name **、逆参照することができます。

#define MY_DATA(bb) \
   (* ((struct a_long_struct_name **) &(bb)->aux) )

これは、示した両方の構成で機能します。

ただし、の具体的な型の可能性のセットが宣言さauxれた時点でわかるstruct basic_block場合は、共用体を使用する方がクリーンです。

struct basic_block
{
  union {
      struct a_long_struct_name *alsn;
      /* etc */
  } aux;

  /* Many other fields,
     which are irrelevant.  */
};

その後

#define MY_DATA(bb) ((bb)->aux.alsn)
于 2012-06-20T15:51:54.907 に答える
1

できません。C では、ある型 ( ) のオブジェクトにvoid *別の型 ( ) の左辺値式を介してアクセスすることを禁止してstruct a_long_struct_name *おり、この規則を破るとエイリアシング違反になります。これが実際的な観点から意味することは、コンパイラーはこれら 2 つの左辺値が同じメモリーを参照できないと想定できるため、コードをひどく壊すような方法で読み取りと書き込みの順序を変更する可能性があるということです。正式には、これは未定義の動作であり、何かが起こる可能性があることを意味します。

あなたがすべきことは、質問で元のバージョンのコードを使用MY_DATA(bb)し、左辺値として使用することを忘れることです。代わりに、 に直接代入してbb->auxください。これがvoid *目的です。

于 2012-07-08T14:25:31.357 に答える