如何通过结构内的联合访问C结构

时间:2019-01-10 16:02:14

标签: c struct unions

我正在使用别人的C代码,他们在其中定义了以下内容:

typedef struct {

  union{

    struct{
      int A;    // some data
     } structA;

    struct{
       char B;  // some alternative data
    } structB;

  } myUnion;

} myStruct;

Youch。在代码的前面,这些巨型结构被声明,malloc并用数据填充。我正在代码的下一部分中工作,在该部分中,将向我传递指向这些结构之一的指针,并且必须(A)确定是否使用structA或structB类型,然后(B)读取实际数据。像这样:

void myFunction(myStruct *s){

   if(s->myUnion.structA != NULL)      // compilation error here
      printf("This myStruct uses a structA, internal data is: %d\n", s->myUnion.structA.A);
   else
      printf("This myStruct uses a structB, internal data is: %c\n", s->myUnion.structB.B);

}

显然以上代码无法编译:

me@Linux:/home/me# gcc -Wall structsUnions.c
structsUnions.c: In function 'myFunction':
structsUnions.c:22:19: error: invalid operands to binary != (have 'struct <anonymous>' and 'void *')
   if(s->myUnion.structA != NULL)
                         ^
me@Linux:/home/me#

但是我很想知道这里的语法。

必须有一种方法可以深入myStruct并确定structA或structB是否在myUnion内部。

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

myUnion是union,而不是具有两个成员的结构。
这意味着structAstructB共享相同的内存(在大多数C实现中)。
这也意味着char Bint A共享相同的内存(同样,在大多数C实现中),因此实际上没有办法确定使用了哪种结构。
ANSI定义工会至少要和最大会员一样大,并且必须拥有其中一个会员。
它旨在实现对所有成员重用相同内存的有效实现。
当然,在某些实现中,对齐问题可能会导致某些成员不与其他成员重叠,但是我想不到一个我知道最大成员无法对齐的成员。

答案 1 :(得分:1)

由于您共享的代码不包含标记字段,该标记字段指示实际上是使用A还是B成员,因此没有任何具体方法可以确定在任何特定情况下预期使用的成员。

但是,根据所获取的数据,您可能可以在代码中进行有根据的猜测。例如,假设我在将IEEE 754用于浮点类型的系统上具有以下联合:

typedef union _F_or_I
{
    float f;
    int32_t i;
    uint32_t bits;
} F_or_I;

如果前9位(符号和指数)全为0,则可能不是浮点数:

F_or_I foo = /* some value */;

if(!(foo.bits & 0xFF800000))
{
      // access member 'i'
}
else
{
      // access member 'f'
}

当然,这种方式并不总是准确的,具体取决于您在联合中使用的确切类型(在示例中,我什至不依赖它!)以及正确的方式为此,是在父struct中包括一个“标记”成员,该成员指示打算访问联合的哪个成员。

答案 2 :(得分:1)

特别是,if(s->myUnion.structA != NULL)中的编译错误是因为您不能检查struct是否为null,而只能检查struct的成员是否为零:

if(s->myUnion.structA.A != 0)