如何使用结构中的联合访问 C 结构

How to access C structs with a union within a struct

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

typedef struct {

  union{

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

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

  } myUnion;

} myStruct;

你好。在代码的前面,这些巨型结构被声明、分配和填充数据。我正在处理后面的代码部分,我将在其中传递一个指向这些结构之一的指针,并且必须 (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 中。

有什么想法吗?

myUnion 是一个 union,不是一个有两个成员的结构。
这意味着 structAstructB 共享相同的内存(在大多数 C 实现中)。
它还意味着 char Bint A 共享相同的内存(同样,在大多数 C 实现中),因此实际上没有办法判断使用了哪个构造。
ANSI 定义一个联合至少与其最大的成员一样大,并且它必须持有其中一个成员。
它的目标是高效实现所有成员重用相同的内存。
当然,在某些实现中,对齐问题可能会导致某些成员不与其他成员重叠,但我想不出一个我所知道的不与最大成员对齐的成员。

由于您共享的代码不包含指示 AB 成员是否实际使用的标记字段,因此没有具体的方法可以确定在任何具体实例。

但是,根据您获得的数据,您可能能够在您的代码中做出有根据的猜测。例如,假设我在使用 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 中包含一个 'tag' 成员,指示要访问哪个联合成员。

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

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