包含union的struct包含指向自我的结构指针'。'访问而不是' - >',困惑

时间:2015-01-20 02:39:19

标签: c pointers struct unions

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

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是一个指针?

编译时,我收到警告"声明没有声明任何内容"在"第123行"在上面的结构s1中。我已经阅读了有关此问题的其他问题,似乎我需要将联合声明做为: union su { ... } SU;
然后由于显而易见的原因导致编译错误。当然,更正s2_ptr->data.SU.array[1].charptr的调用可以修复错误。我想知道这是否会以任何方式改变数据访问方式的变化?会有什么变化吗?

感谢您的帮助。

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

3 个答案:

答案 0 :(得分:3)

  

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

array[1]不是指针。

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


问题的另一部分:如果你有这样的代码:

union foo
{
    int x;  
    // etc
};

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

要声明变量,你必须写:

union foo SU;

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

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

答案 1 :(得分:1)

编译器抱怨,因为你没有声明工会成员,你只是定义工会。

你的结构和结合是相互依赖的。解决这个问题的最佳方法是首先对它们进行原型设计:

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

答案 2 :(得分:1)

已经处理了union个问题,但(到目前为止)我没有看到关于指针/数组符号问题的非常好的解释:

  

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

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

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

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