嵌套结构体

结构体也是一种递归定义:结构体的成员具有某种数据类型,而结构体本身也是一种数据类型。换句话说,结构体的成员可以是另一个结构体,即结构体可以嵌套定义。以下的例子中,每个结构体、联合,都可以换成结构体联合、或者类。

 

一、结构体的声明与定义变量的方法

1.常规方法

struct AA
  {
     int a;
     int b;
  }

此时定义变量可以 AAaa; 调用成员 aa.a; aa.b;

2.也可以先在结构体尾部定义一个或者几个变量。

struct CC 
  {
    int a;
    int b;
   }x1,x2;

  此时x1,x2就是已经定义好的CC类型的变量了,这种情况在声明时struct前就一定不能加typedef,如果加上了,x1,x2就成了和CC一样的结构体类型了,而不是变量了。

3.无名结构体,指的是此结构体在声明时没有写名字的情况。

   这时如果结构体不是子结构体,那么就必须定义一个变量,用第二种方法。否则此结构体无意义了。

   如果此结构体是子结构体,那么此结构体可以定义变量,也可以不定义。如果不定义变量,那么它的成员就会被当成父结构体的直接成员,直接调用。如果定义变量,那么就要通过两级调用才能调用这个结构图的成员。

4. 用typedef的情况。这种情况,定义变量必须在结构体声明之后定义。

  使用typedef可以在结构体外部顺便定义此结构体的别名、指针类型、二级指针类型、数组类型等。

typedef struct _ABC
 {
    int a;
    int b;
 }ABC,*pABC,ABC_ARRY[20];

 注意和第二种情况的区别,一个是实例,一个是类型

 

二、结构体嵌套使用方法

1.可以先把子结构体在父结构体之外声明,然后就在父结构体内部把子结构体当成一个普通类型来使用就可以了,不过此时子结构体必须有名字(order就是名字)。这样的好处就是可以在父结构体内部定义多个子结构体类型的成员变量。这时调用子结构体的变量就得通过两级调用了。即aa.order.first;

struct ORDER
{
    BYTE first;
    BYTE second;
    BYTE third;
    BYTE forth;
}bb; 
union OpcondOrder
{
     DWORD data;
     ORDER order;
}aa;

2.把子结构体在父结构体内部定义的情况:

  a. 如果内部定义的子结构体没有名字,那么定义完父结构体后,就把子结构体的成员当成父结构体的第一级成员(直接成员)来调用就行了。此时子结构体不能定义变量。

union OPCODEORDER
 { 
    DWORD data;
    struct           //没有名字不能定义变量
    {
                  BYTE forth;
                  BYTE third;
                  BYTE second;
                  BYTE first;
    };              //没有变量
 }aa;

  这时就可这样调用:aa.first;aa.second;直接当成自己的一级成员来用。 //这时这个结构体没有意义

  如果此时作为子结构体的 无名结构体定义了变量,那么就需要二级调用才能够调用无名结构体的成员。

union OPCODEORDER
{
   DWORD data;
    Struct
{
        BYTE forth;
        BYTE third;
        BYTE second;
        BYTE first;
    }cc;
}aa;

  这时调用就需要:aa.cc.first;aa.cc.second;当成父结构体的二级成员调用。

  b. 对于内部定义的结构体有名字的情况,如果此有名子结构体没有定义变量,那么在调用的时候就要通过二级调用,而且第二级调用要用类作用域区分符(::),否则会报错。

union OPCODEORDER
{
    DWORD data;
    struct ORDER
{            //有名字,就要类作用域区分符,'::'
             BYTE forth;      
             BYTE third;
             BYTE second;
             BYTE first;
         };
}aa;

 此时就得这样调用 aa.ORDER::first;aa.ORDER::second;aa.ORDER::third;

 如果有名字的结构体定义了变量,那么调用时也是通过两种二级调用,此时就是普通的二级调用了和用类作用域区分符(::),就兼容了第一种情况的调用方法和上面的这种方法。

union OPCODEORDER
{
  DWORD data;
  struct ORDER
{
          BYTE forth;
          BYTE third;
          BYTE second;
          BYTE first;
}cc;
}aa;

  第一种调用方法aa.cc.first;aa.cc.second;

  第二种调用方法 aa.ORDER::first;aa.ORDER::second;