博主不定期更新【保研/推免、C/C++、5G移動通信、Linux、生活隨筆】系列文章,喜歡的朋友【點贊+關注】支持一下吧!
Lecture 6 結構類型
1. 枚舉
- 常量符號化
用符號而不是具體的數字來代表程序中的數字; - 用枚舉而不是定義獨立的const int變量
枚舉是一種用戶定義的數據類型,它用關鍵字enum以如下語法來聲明:
enum 枚舉類型名字 {名字0,...,名字n};
枚舉類型名字通常並不真的使用,要用的是在大括號裏的名字,因爲它們就是常量符號,它們的類型是int,值則依次從0到n。如:
enum colors {red,yellow,green}
就創建了三個常量,red的值是0,yellow是1,而green是2.
當需要一些可以排列起來的常量值時,定義枚舉的意義就是給了這些常量值名字。
套路:自動計數的枚舉
enum colors {red,yellow,green,Numofcolors}
Numofcolors
值爲3即爲前面提到的顏色的總數目,這樣需要遍歷所有的枚舉量或者需要建立一個用枚舉量做下標的數組時就很方便。
聲明枚舉量的時候可以指定值
enum color {red=1,yellow,green=5} // 1,2,5
enum color COLOR=0;//即使給枚舉類型的變量賦不存在的整數值也沒有warning或error
- 雖然枚舉類型可以當做類型使用,但是實際上很少用
- 如果有意義上排比的名字,用枚舉比const int方便
- 枚舉比宏(macro)好,因爲枚舉有int型
2. 結構
2.1 結構類型
聲明結構類型:
#include <stdio.h>
int main()
{
struct date{ //聲明一種新的結構類型
int month;
int day;
int year;
}; //分號別忘
struct date today;//定義一個結構變量today,其類型爲struct date
today.month = 07;
today.day = 31;
today.year = 2014;
printf("Today's date is %i-%i-%i.\n", today.year, today.month, today.day);
return 0;
}
- 和本地變量一樣,在函數內部聲明的結構類型只能在函數內部使用
- 所以通常在函數外部聲明結構類型,這樣就可以被多個函數所使用
聲明結構的形式:
形式一:
struct point {
int x;
int y;
};
struct point p1,p2;//p1和p2都是point結構變量,裏面有x和y的值
形式二:
struct {
int x;
int y;
} p1,p2; //p1和p2都是無名結構,裏面有x和y的值
形式三:
struct point {
int x;
int y;
} p1,p2;//p1和p2都是point結構變量,裏面有x和y的值
結構變量的初始化:
struct date today = {07,31,2014};
struct date thismonth = {.month=7, .year=2014};//沒賦值默認爲0即day=0
結構成員:
- 結構和數組有點像
- 數組用[]運算符和下標訪問其成員
a[0]=10;
- 結構用
.
運算符和名字訪問其成員today.day; student.firstName; p1.x; p1.y;
.
的左邊必須是一個結構
結構運算:
- 要訪問整個結構,直接用結構變量的名字
- 對於整個結構,可以做賦值、取地址,也可以傳遞給函數參數
p1 = {struct point}{5,10}//相當於p1.x=5; p1.y=10;
p1 = p2; //相當於p1.x=p2.x; p1.y=p2.y;
數組無法做這兩種運算!
結構指針:
- 和數組不同,結構變量的名字並不是結構變量的地址,必須使用&運算符
struct date *pDate = &today;
2.2 結構與函數
結構作爲函數參數
int numberofDays(struct date d)
- 整個結構可以作爲參數的值傳入函數
- 這時候是在函數內新建一個結構變量,並複製調用者的結構的值
- 也可以返回一個結構
- 這與數組完全不同
輸入結構
- 沒有直接的方式一次
scanf
一個結構
解決方案
- 在這個輸入函數中,完全可以創建一個臨時的結構變量,然後再把這個結構返回給調用者,之後可以通過賦值在主函數中進行運算;
輸入結構 方式1:
struct point getStruct(void)
{
struct point p;
scanf("%d", &p.x);
scanf("%d", &p.y);
return p;
}
- 結構指針作爲參數(更常用)
首先看看指向結構的指針:
struct date{
int month;
int day;
int year;
}myday;
struct date *p = &myday;
(*p).month = 12;
p->month = 12; //用->表示指針所指的結構變量中的成員
輸入結構 方式2:
struct point* getStruct(struct point* p)
{
struct point p;
scanf("%d", &p->x);
scanf("%d", &p->y);
return p;
}
2.3 結構中的結構
結構數組:
struct date dates[100];
struct date dates[]={
{4,5,2005},{2,4,2005}
};
結構中的結構:
struct point{
int x;
int y;
};
struct rectangle{
struct point pt1;
struct point pt2;
};
如果有變量定義:
struct rectangle r, *rp;
rp = &r;
那麼下面四種形式等價:
r.pt1.x
rp->pt1.x
(r.pt1).x
(rp->pt1).x
但是沒有rp->pt1->x (因爲pt1不是指針)
3. 聯合
3.1 類型定義
如何擺脫struct
自定義數據類型(typedef)
- C語言提供了一個叫做
typedef
的功能來聲明一個已有的數據類型的新名字,例如typedef int Length;
使得Length
成爲int
類型的別名。這樣,Length
這個名字就可以代替int出現在變量定義和參數聲明的地方了,例如Length a,b,len; Length numbers[10];
Typedef:聲明新的類型的名字
typedef long int64_t; //重載已有的類型名字,新名字的含義更清晰,具有可移植性
typedef struct ADate{
int month;
int day;
int year;
} Date; //簡化了複雜的名字
int 64_t i = 100000000000;
Date d = {9, 1, 2005}; //此處Date相當於struct ADate
有了typedef,便可以:
typedef struct{ //此處不關心該結構的名字
int month;
int day;
int year;
} Date; //定義一個無名結構,之後命名爲Date
3.2 聯合
- 存儲:所有的成員共享一個空間;同一時間只有一個成員是有效的;union的大小是其最大的成員;
- 初始化:對第一成員做初始化。
常用場合:得到一個整數(int)的內部字節(同理可得double/float)
#include <stdio.h>
typedef union {
int i;
char ch[sizeof(int)];
} CHI;
int main()
{
CHI chi;
chi.i = 1234;
int j;
for ( j=0; j<sizeof(int); j++) {
printf("%02hhX", chi.ch[j]);
}
printf("\n");
return 0;
}
拓展知識:x86架構,小端,在內存中存放數據時,低位在前。