包含包含指向自身的结构指针的联合的结构使用“。”访问而不是'->',混淆

Struct containing union containing struct pointer to self uses '.' access instead of '->', confused

在我正在处理的代码库中,我定义了两个结构,如下所示:

typedef struct s1
{
   int   somedata;
   union su
   {
      char      *cptr;
      struct s1 *array;
   }; //line 123
} S1;

typedef struct s2
{
    S1   data;
} S2;

在其他地方,这些结构和成员的访问方式让我感到困惑:

S2   *s2_ptr;
s2_ptr->data.array[1].charptr

所以我有问题:

为什么是 array[1].charptr 而不是 array[1]->charptr 因为 array 是一个指针?

编译时,我在上面的结构 s1 中的 "line 123" 上收到警告 "declaration does not declare anything"。我已经阅读了有关此的其他问题,看来我需要使联合声明类似于:
union su { ... } SU;
然后由于明显的原因导致编译器错误。当然,然后更正对 s2_ptr->data.SU.array[1].charptr 的调用可以修复错误。我想知道这是否会以任何方式改变数据访问方式中发生的事情?会有什么变化吗?

感谢您的帮助。

*非常感谢您的所有回答。把我清理干净了。

Why is it array[1].charptr and not array[1]->charptr since array is a pointer?

array[1] 不是指针。

如果代码是 array->charptr 那么你是对的;但事实并非如此。 array[1] 是一个 struct s1 。 (这与工会无关)


你问题的另一部分:当你有这样的代码时:

union foo
{
    int x;  
    // etc
};

然后这定义了一个名为 union foo 类型 ,但没有声明该类型的任何实例。如果您在结构定义中,那不会改变。

要声明变量,您必须编写:

union foo SU;

或者您可以通过将变量名放在类型定义末尾的 ; 之前来同时完成这两件事。

C11 中有一个名为 anonymous unions 的东西,在此之前由一些编译器作为扩展提供。但是,要激活匿名联合,您必须取出联合标记,因此代码以 union { 打开。

编译器报错,因为你没有声明联合成员,你只是在定义联合。

你的结构和联合是相互依赖的。解决这个问题的最好方法是先制作原型:

union  myUnion;
struct myFistStruct;
struct mySecondStruct;

然后你就可以正确定义它们了:

union myUnion
{
    char *pC;
    struct myFistStruct *pS1;
};

struct myFistStruct
{
    int D;
    union myUnion U;
};

struct mySecondStruct
{
    struct myFistStruct S1;
};

关于 .-> 运算符。一个单一的规则,你永远不会感到困惑;让我们考虑这个表达式:

(左操作数)(运算符)(右操作数)

如果左操作数是结构或联合本身,则运算符是 (.),如果左操作数是指向结构或联合的指针,则运算符是 (->).

因此有效的访问表达式如下:

struct mySecondStruct *pS2 = (struct mySecondStruct*)malloc(sizeof(struct mySecondStruct));

// pS2->S1
// pS2->S1.D
// pS2->S1.U
// pS2->S1.U.pC
// pS2->S1.U.pS1

union问题已经解决,但是(到目前为止)我没有看到对你的指针/数组表示法问题的很好解释:

Why is it array[1].charptr and not array[1]->charptr since array is a pointer?

array 确实是一个指针,并且 大概 (但不是在您发布的代码中)它被初始化为指向一个足够大的内存块对于至少 2 s1 个对象。当代码引用 s2_ptr->data.SU.array 时(当然要加上 union 字段名)那么你指的是指向这块内存的指针,它可以看作是 s1 对象的数组。所以 s2_ptr->data.SU.array[1] 指的是该数组中的第二个对象。由于您指的是特定对象,因此您使用点符号来访问其字段 - s2_ptr->data.SU.array[1].charptr

如果您想访问该数组中的 first 对象,您可以使用 s2_ptr->data.SU.array->charptrs2_ptr->data.SU.array[0].charptr

C 提供了几种解引用指针的方法,即通过指针访问特定对象:*pp->p[i] 都是非常密切相关的解引用操作。