我正在使用别人的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内部。
有什么想法吗?
答案 0 :(得分:2)
myUnion是union
,而不是具有两个成员的结构。
这意味着structA
和structB
共享相同的内存(在大多数C实现中)。
这也意味着char B
和int 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)