1. 程式人生 > >結構體(struct)

結構體(struct)

二叉樹 table sel 包含 list 4.2 我們 通過 div

結構體

結構體是將不同類型的數據安裝一定的功能需求進行整體封裝,封裝的數據類型與大小均可以由用戶指定。

1 結構體的聲明、定義及初始化

1.1 聲明結構體類型

struct 結構體名
{
  成員列表;
};
struct STUDENT
{
  char name[20]; //名字
  int age;   //年齡
  char sex;  //性別
  int num;  //學號
  char add[30];  //家庭住址
  float score;   //分數
};

1)結構體類型是由基本數據類型組合而成的新的數據類型。結構體類型的成員是由程序員自己定義的,所以結構體類型是由我們人為定義的數據類型

2)struct STUDENT是定義的數據類型名字(與系統提供的int,char,float,double等提供的標準類型名一樣,都是數據類型,具有相同的作用,都是用來定義變量的),它向編譯系統聲明這是一個結構體類型。

3)聲明結構體類型僅僅是聲明了一個類型,系統並不為之分配內存,好比系統不會類型為int分配內存一樣。只有當使用這個類型定義了的變量時,系統才會為變量分配內存。所以在聲明結構體類型的時候,不可以對裏面的變量進行初始化

1.2 定義結構體變量

定義結構體變量有兩種方法:

1)先聲明結"構體類型",再定義"結構體類型變量"

struct STUDENT stud1,stud2;

stud1,stud2就是我們定義的結構體變量名。定義了結構體變量之後,系統就會為之分配內存單元

2)聲明結構體類型的同時定義結構體變量

struct STUDENT
{
  char name[20]; //名字
  int age;   //年齡
  char sex;  //性別
  int num;  //學號
  char add[30];  //家庭住址
  float score;   //分數
}stud;

聲明了一個結構體類型(struct STUDENT),並用這個類型定義了一個結構體變量stud。

註:結構體變量不能相加、不能相減、不能相乘、不能相除。但結構體變量可以相互賦值,可以將一個結構體變量賦值給另一個結構體變量,前提是這兩個結構體變量的結構體類型必須相同

1.3 結構體變量的引用

由於結構體變量中有多個不同類型的成員,所以結構體變量成員不能整體引用,只能一個成員一個成員的引用。

1)引用方式:

結構體變量名.成員名

2)可以引用"結構體變量成員"的地址,也可以引用"結構體變量的"地址

&stud1.num //stud1.num成員在內存中的首地址
&stud1     //stud1在內存中的首地址

結構體變量的首地址,就是結構體第一個成員的首地址。&stud1等價於第一個成員name的首地址,而name是一個數組,數組名表示數組的首地址,所以&stud1與stud1.name是等價的。等價僅僅指的是它們表示"同一個內存空間的地址"但它們的類型是不同的,&stud1是結構體變量地址,是struct STUDENT*型的,而stud1.name是數組名,是char*型的,類型不同所以在程序中不能互換

2 結構體字節對齊

2.1 例一

#include <stdio.h>
struct DATA
{
  int m;
  char n;
}DATA;

int main()
{
  printf("%p,%p\n",&DATA.m,&DATA.n);
  printf("%d\n",sizeof(DATA));
}

/***********************************
輸出:
      001A7560,001A7564
      8
************************************/

我們看到DATA不是占5字節,而是占8字節。變量m的地址是從001A7560到001A7563占4字節;變量n的地址是從001A7564到 001A7567,也占4字節。m占4字節我們能理解,但n是char型,char型不是占1字節嗎,這裏為什麽占4字節?其實不是它占了4字節,它占的還是1字節,只不過結構體中有一個字節對齊的概念。

字節對齊:結構體是一種構造數據類型,裏面可以有不同數據類型的成員。這些成員中,不同數據類型所占的內存空間不同。通過例子可以看出結構體變量成員分配內存不是順序存儲,而是按字節對齊的方式存儲。即結構體成員中占內存最多的數據類型所占的字節數為標準,所有成員在分配內存是都要與這個長度對齊

m
n

所謂的空並不是裏面什麽都沒有,它就同定義了一個變量沒有初始化一樣,裏面是一個很小的負的填充字,在此只是為了便於表達。

2.2 例二

#include <stdio.h>
struct DATA
{
  int m;
  char n;
  char i;
}DATA;

int main()
{
  printf("%p,%p,&p\n",&DATA.m,&DATA.n,&DATA.i);
  printf("%d\n",sizeof(DATA));
}

/***********************************
輸出:
      001A7560,001A7564,001A7565     
      8
************************************/
m
n i

3 結構體數組

結構體數組的每一個元素都是一個結構體類型的變量,都包含結構體中的所有成員。

1)定義結構體數組(同定義結構體變量一樣,只不過將變量改為數組)

struct STUDENT stud[5];//定義了一個結構體數組,裏面包含5個元素,每個元素都是一個結構體變量,包含結構體所有成員

for(i=0;i<5;i++)
{
  printf("%s%d %c%d",stud[i].name,stud[i].age,sutd[i].sex,stud[i].num);
}

結構體數組的引用與引用一個結構體變量在原理上是一樣的。只不過結構體數組中有多個結構體變量,只需利用for循 環一個一個地使用結構體數組中的元素。

4 結構體指針

4.1 指向結構體變量的指針

指向什麽結構體類型的結構體變量,就要定義成什麽樣的結構體類型。比如指向 struct STUDENT 類型的結構體變量,那麽指針變量就一定要定義成 struct STUDENT* 類型

struct STUDENT *p //定義一個結構體指針變量
(*p).name //

指針引用結構體變量成員方式:

(*指針變量名).結構體成員名 或者 指針變量名->結構體成員名

註:只有指針變量名後面才能加"->"

4.2 指向結構體數組的指針

結構體數組的每一個元素都是一個結構體變量。如果定義一個結構體指針變量並把結構體數組的數組名賦給這個指針變量的話,就意味著將結構體數組的第一個元素,即第一個結構體變量的地址,也即第一個結構變量中的第一個成員的地址賦給了這個指針變量。

5 結構體類型的定義

結構類型無法將自己的類型作為其成員的類型,因為自己的類型定義尚不完整,要在結束的大括號(})後才算定義完整。然而,結構類型可以包含指向自己類型的指針,這樣的應用很常見。例如,在實現鏈表(linked list)和二叉樹(binary tree)時,就會用到這種自引用結構(self-referential structure)。

struct Cell
{ 
  struct Song song;        // 這條記錄的數據
  struct Cell *pNext;      // 指向下一條記錄的指針          
};

結構體(struct)