0

这是程序中使用的结构:

struct basic_block
{
  void * aux;

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

现在:

  1. basic_block在程序执行期间存在几个实例。
  2. 该程序分阶段/通过,一个接一个地执行。
  3. aux字段用于在阶段basic_block执行期间存储阶段和特定数据,并由阶段本身释放(以便下一阶段可以重用它)。这就是为什么它是一个void *.

我的舞台用来aux存储 a 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) 自身用作 L 值(对于 a 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 **转换为然后取消引用它:

#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 回答
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 回答
1

你不能。void *C 禁止通过不同类型 ( ) 的左值表达式访问一种类型 ( ) 的对象struct a_long_struct_name *,违反此规则是违反别名的行为。从实际的角度来看,这意味着编译器可以假设这两个左值不能引用相同的内存,因此可能会以严重破坏代码的方式重新排序读取和写入。形式上,它只是未定义的行为,这意味着任何事情都可能发生。

您应该做的是在问题中使用您的代码的原始版本,而忘记MY_DATA(bb)用作左值。而是直接分配给bb->aux. 这是void *为了什么。

于 2012-07-08T14:25:31.357 回答