(一)結構體類型程序員
1.簡介:數組
例:函數
struct datespa
{指針
int month;內存
int day;原型
int year;string
};io
struct student編譯
{
int num;
char name[20];
char sex;
int age;
struct date birthday; /*birthday 是 struct date 類型*/
char addr[30];
}student1,student2;
(1):結構體可嵌套
(2):與枚舉相比結構體內元素爲變量,而枚舉爲常量
(3):元素只能單個引用:如:student.num; student.birthday.month;
(4):內部元素變量能夠與其餘變量重名且互不影響;
(5):賦值:student.num = 10010;
2.初始化
(可直接賦值)
struct student
{
long int num;
char name[20];
char sex;
char addr[20];
}a = {10101,"Li Lin","M","BeiJing Road"};
3.結構體數組
struct student
{
int num;
char name[20];
char sex;
int age;
struct date birthday; /*birthday 是 struct date 類型*/
char addr[30];
};
struct student stu[3];
注:數組中每個元素都是一個結構體類型數據;
4.指向結構體類型數據的指針
struct student
{
int num;
char name[20];
char sex;
int age;
struct date birthday; /*birthday 是 struct date 類型*/
char addr[30];
};
struct student stu_1;
struct student *p;
p = &stu_1;
在實例化結構體指針時,務必先malloc分配對應的地址(在堆中開闢);
使用指針務必在堆中開闢地址空間,以避免出現野指針;
注:
(1)一個結構體變量的指針就是該變量所佔據的內存段的起始地址(開頭地址);
(2)(*p).num 等價於 stu_1.num;(*p兩端的括號不能省略)
(3)(*p).num 等價於 p->num; (-> 稱爲指向運算符)
(4)以下運算
p->n; 獲得p指向的結構體變量中的成員n的值。
p->n ++;獲得p指向的結構體變量中的成員n的值,用完該值後使它加1。
++ p->n;獲得p指向的結構體變量中的成員n的值加1,而後再使用它。
-> 運算優先級大於 ++;
5.指向結構體數組元素的指針
struct student
{
int num;
char name[20];
char sex;
int age;
struct date birthday; /*birthday 是 struct date 類型*/
char addr[30];
};
struct student stu[3];
struct student *p;
for( p = stu;p < stu + 3;p ++)
printf( "%5d %-20s %2c %4d\n",p->num,p->name,p->sex,p->age);
注:p是一個指向struct student 類型數據的指針變量,它用來指向一個struct student 類型的數據(及:stu數組的一個元素如stu[0],stu[1],的起始地址),不該用來指向stu數組元素中的某一成員,
p = stu[1].name; 這樣的用法是錯誤的
可是:
強制類型轉換後能夠用
p = (struct student *)stu[0].name; 這樣是正確的;
這樣的話:p的值是stu[0]元素的name成員的起始地址。printf(「%s」,p)輸出stu[0]中成員name的值。但printf(「%s」,p +1)則輸出 stu[1]中name的值。p+1 的值是在p值的基礎上加上結構體struct student的字節長度。
由於:p加減運算他的類型就是他的最小運算單元
6.結構體變量作函數參數
注:用結構體變量作函數參數時,採用值傳遞的方式,將結構體變量所佔的內存單元的內容所有順序傳遞給形參。
#include<stdio.h>
#include<string.h>
#define FORMAT "%d\n%s\n%f\n%f\n%d\n"
struct student
{
int num;
char name[20];
float score[3];
} ;
void main()
{
void print(struct student);
struct student stu;
stu.num = 12345;
strcpy(stu.name,"Li Li");
stu.score[0] = 67.5;
stu.score[1] = 89;
stu.score[2] = 78.6;
print(stu);
}
void print(struct student stu)
{
printf(FORMAT,stu.num,stu.name,stu.score[0], stu.score[1],stu.score[2]);
printf("\n");
}
運行結果:
12345
Li Li
67.500000
89.000000
78.599998
7.用指針處理鏈表
例:
#include<stdio.h>
#define NULL 0
struct student
{
long num;
float score;
struct student *next;
};
void main()
{
struct student a,b,c,*head,*p;
a.num = 10101;a.score = 89.5;
b.num = 10103;b.score = 90;
c.num = 10107;c.score = 85;
head = &a;
a.next = &b;
b.next = &c;
c.next = NULL;
p = head;
do
{
printf("%ld%5.1f\n",p -> num,p -> score);
p = p -> next; //使P指向下一結點
}
while(p != NULL);
}
運行結果:
10101 89.5
10103 90.0
10107 85.0
注:
該例子結點都是在程序中定義的,不是臨時開闢的,也不能用完後釋放,這種鏈表稱爲「靜態鏈表」。
8.處理動態鏈表
①malloc函數
原型:void *malloc(unsigned int size)
其做用是在內存的動態存儲區分配一個長度爲size的連續空間。此函數的值(即「返回值」)是一個分配域的起始地址(類型爲void)。若是此函數未能成功地執行(例如內存不足),則返回空指針(NULL)。
②calloc函數
原型:void *calloc(unsigned n unsigned int size);
其做用是在內存的動態存儲區分配n個長度爲size的連續空間。函數返回一個指向分配域起始位置的指針;若是分配不成功,返回NULL;
③free函數
原型:void free (void *p);
其做用是釋放由p指向的動態存儲區,使這部份內存區能被其餘變量使用。p是最近一次調用calloc或malloc函數時返回的值。free函數無返回值。
9.創建動態鏈表
------------------------------------------------------------------------------------
(二)共用體
1.概述:使幾個不一樣的變量共佔同一段內存的結構,稱爲「共用體」類型的結構;
2.定義
union 共用體名
{
成員表列;
}變量表列;
如:
union data
{
int i;
char ch;
float f;
}a,b,c;
或者
union data
{
int i;
char ch;
float f;
};
union data a,b,c;
注:共用體與結構體定義形式類似,但佔內存不一樣,結構體佔的是各個成員內存和,共用體的內存是成員中字節最長的那個;
3.共用體變量的引用方式
必須先定義後引用,引用時只能引用共用體變量中的成員。
如:
a.i
a.ch
a.f
4.共用體類型數據的特色
(1)同一個內存段能夠用來存放幾種不一樣類型的成員,但在每一瞬時只能存放其中一種,而不是同時存放幾種。因此對於共用體變量中起做用的成員是最後一次存放的成員。
如:
a.i = 1;
a.c = 'a';
a.f = 1.5;
只有a.f 是有效的,a.i ,a.c已經無心義了,此時用"printf("%d",a);"是不行的,"printf("%d",a.i);"是不行的,"printf("%d",a.f);"能夠;
(2)共用體變量的地址、它的各成員的地址都是同一地址。
即:&a, &a.i, &a.c, &a.f都是同一地址;
(3)不能對共用體變量名賦值,不能賦值給共用體名,不能定義共用體時對它初始化。
①
union data
{
int i;
char ch;
float f;
}a={1,'a',1.5}; 錯誤
②
a = 1; 錯誤
m =a; 錯誤
(4)不能把共用體變量做爲函數參數,也不能使函數帶回共用體變量,但能夠使用指向共用體變量的指針(和結構體變量這種用法相仿)。
(5)共用體類型能夠出如今結構體類型定義中,也能夠定義共用體數組。反之,結構體也能夠出如今共用體類型定義中,數組也能夠做爲共用體的成員。
------------------------------------------------------------------------------------
(三)枚舉類型
1.enum weekday{sum,mon,tue,wed,thu,fri,sat};(枚舉定義的量都爲常量)
聲明一個枚舉類型 enum weekday,能夠用此類型來定義變量。如:
enum weekday workday,week_end;
workday和week_end被定義爲枚舉變量,它們的值只能是sum到sat之一。如:
workday = mon;
week_end = sum;
等價於
enum {sum,mon,tue,wed,thu,fri,sat} workday,week_end;
它們都是其中之一。
2.固然能夠用
typedef enum {sum,mon,tue,wed,thu,fri,sat} weekday;
即等價於 enum weekday{sum,mon,tue,wed,thu,fri,sat};
3.枚舉類型特色
(1)枚舉元素做爲常量,它們是有值的,C語言編譯按定義時的順序使它們的值爲 0,1,2.....
①
在上面定義中,sun的值爲0,mon的值爲1......sat的值爲6。
例如:
printf("%d",workday);
將輸出整數 1。
②
能夠在定義式對元素賦初值
如:
enum weekday {sum =7,mon =1,tue,wed,thu,fri,sat} workday,week_end;
定義sun爲7,mon爲1,其餘值仍是按順序給值,即sat任爲6。
③枚舉類值可比較大小作判斷。
(2)一個整數不能直接賦給一個枚舉變量
如:
workday = 2; 錯誤
但可
workday = (eunm weekday)2; 正確