感谢原创作者!

结构体定义:

大家都知道若struct后面接的是名字,则其为该结构体的名称。

下面给出六种结构体定义,其中第一种是最基本的结构体定义,其定义了一个结构体A。

struct A            //第一种
{
    int a;
};
  • 第二种则是在定义了一个结构体B的同时定义了一个结构体B的变量m。
struct B            //第二种
{
    int b;
}m;
  • 第三种结构体定义没有给出该结构体的名称,但是定义了一个该结构体的变量n,也就是说,若是想要在别处定义该结构体的变量是不行的,只有变量n这种在定义结构体的同时定义变量才行。
struct              //第三种
{
    int c;
}n;
  • 第四种结构体定义在第一种结构定义的基础上加了关键字typedef,此时我们将struct D{int d}看成是一个数据类型,但是因为并没有给出别名,直接用D定义变量是不行的。如D test;,不能直接这样定义变量test。但struct D test;可行。
typedef struct D    //第四种
{
    int d;
};
  • 第五种结构体定义在第四种结构体定义的基础上加上了别名x,此时像在第四种结构体定义中说得那样,此时的结构体E有别名x,故可以用x定义E的结构体变量。用E不能直接定义,需要在前面加struct,如struct E test;。
typedef struct E    //第五种
{
    int e;
}x;
  • 第六种结构体定义在第五种的基础上减去了结构体名,但是若是直接使用y来定义该结构体类型的变量也是可以的。如y test;。
typedef struct      //第六种
{
    int f;
}y;
  • 其他:转自:

可以看出,上面的区别在于 typedef struct 后面一个跟了标识符,另外一个没有跟标识符,这两个有什么区别呢?这里的os_tcb代表什么?OS_TCB的意义又是什么?

要搞清楚上面的问题,要从两方面入手。

第一 typedef的用法是什么?

typedef是在基本类型的基础上定义类型的同义字。注意typedef并不产生新的类型。例如 typedef int exam_score;这里的exam_score 就是一种基本类型,它的意义等同于 int,那么即可以用它来定义整型变量,例如:exam_score  LIMING。

第二 结构体的定义各个标志符的意义。

在结构体定义中,通常是这样的

struct exam_score
{
     chinese;
     english;
     math;
     physical;
     chemistry;
}LIMING;

这里的struct是结构体关键字,exam_score则是结构体类型名,LIMING则是结构体变量。

弄明白以上两个问题,回过头来看开始的那两个结构体。

typedef struct os_tcb
{
      OS_STK    *OSTCBStkPtr;
      OS_STK    *OSTCBStkBottom;     
      INT32U      OSTCBStkSize;     
      INT16U      OSTCBOpt;         
      INT16U      OSTCBId;            
}OS_TCB; // OS_TCB是一个结构体类型 = struct os_tcb

这里声明一种结构体类型os_tcb,所以os_tcb就是结构体类型名;OS_TCB是struct os_tcb 的同义字,所以可以直接用OS_TCB来定义变量,同时也可以这样 struct os_tcb xxx,OS_TCB xxx;都是合法的,因为OS_TCB 就等同于 struct os_tcb。
 

来看第二种

typedef struct 
{
      OS_STK    *OSTCBStkPtr;
      OS_STK    *OSTCBStkBottom;     
      INT32U      OSTCBStkSize;     
      INT16U      OSTCBOpt;         
      INT16U      OSTCBId;            
}OS_TCB;    // OS_TCB是一个结构体类型 = struct

在结构体的定义中允许这样形式的定义:

struct
{
     xxx
     xxx
     xxx
}var;

这里没有声明结构体变量名,直接定义了结构体变量var,var在这里是结构体变量。这样定义的结果是在程序不能再定义新的结构体变量。

这种形式加上typedef 之后情况就变了,这里的OS_TCB不是结构体变量,而是struct的同义字(结构体类型),这个同义仅限于上面定义的那种情况,可以用OS_TCB来定义结构体变量。

 

总结:

有了以上叙述与理解,我们便可以很容易搞清楚一个易混淆的点:struct{}后面的到底是结构体变量名,还是结构体类型名。

 

当只是定义结构体类型:

struct 结构体名

{

        结构体成员名

 

}结构体变量名;

引用结构体成员方式应是:

结构体变量名. 结构体成员名  //结构体变量直接引用结构体成员

 

当使用typedef定义时:

typedef struct 结构体名

{

        结构体成员名

 

}结构体类型名;

引用结构体成员方式应是:

结构体类型名 xxx;// 定义一个结构体变量

xxx.结构体成员名  // 引用结构体成员

结构体与指针

转自:

一:关于结构体的定义问题:使用结构体一般会使用变量或者定义指针

typedef struct{
int a;
int b;
}data;

使用这个结构体的两种方式:

1、data datas 直接引用。这样使用类似于int a 这种模式。data类似于一个类型(如:int)这样的话,系统自动会为这个类型分配空间。是栈的分配,并且会在自动释放。
2、data *dates 指针调用。定义一个data类型的指针。定义这种指针需要做的是分配空间和释放空间以初始化。

二:关于结构体指针的传递和调用的用法:

typedef struct{
  int a;
  int b;
  }date;
 static int intcms(void *para){
     int c = ((date *)para)->a;
     printf("c is %d\n",c);
 }
  
 int main(int argc, char **argv)
 {
     date dates;
     dates.a = 9;
     dates.b = 2;
     intcms(&dates);
}

上述调用中采用的结构体变量。在传入函数时通过指针void *para指针传递过去。需要注意的是不能直接使用para->a来访问结构体的成员。为什么呢。这是因为para只是接收过来的地址。para虽然指向的结构体的首地址。但是这个指针并不知道自己指向的是什么内容和有多少成员。需要(date *)para强制转化一下。这样para就可以知道自己是什么类型的指针。有多少成员。
 

typedef struct{
  int a;
  int b;
  }date;
 static int intcms(void *para){
     int c = ((date *)para)->a;
     printf("c is %d\n",c);
 }
  
 int main(int argc, char **argv)
 {
     date *dates = (date *)malloc(sizeof(date));
     dates->a = 9;
     dates-> = 2;
     intcms(dates);
	 free(dates);
}

上述代码使用结构体指针需要分配空间和释放空间。这是堆的使用。如果你不释放。在整个进程结束的时候。系统有会自动回收。简单的程序没什么问题。但是在需要分配大量的空间就可能导致出资源浪费或者内存耗尽的情况。

此外,也可以用new的方式,如下

data *datas = new data;

...

delete datas;//释放空间

或者如下:

struct STUDENT
{
	char name[20];
	int num;
};

struct STUDENT student1;
struct STUDENT *p = NULL; // 定义一个 指针变量 p
p = &student1; // p指向结构体变量

&student1和student1.name指向同一个内存单元,但&student1是 struct STUDENT *型的,而student1.name是char *型的,所以在对 p 进行初始化时,“p = &student1;”,不能写成“p = student1.name”。