下面列舉幾種c語言中常用的自定義資料型別:
1. 結構體型別
當描述乙個整型變數時,可以用int,描述字元型變數時,可以用char,但要描述乙個學生時,因為這個學生包含的資訊很多,比如姓名,性別,年齡等,不能通過單一的型別來描述,所以,這裡引入結構體型別,將某個事物的共有屬性集合在一起,宣告乙個結構體型別來描述該事物。
1)結構體型別的宣告,格式如下:
struct tag //結構體型別名
;
注意:
(1)宣告結構體型別時,必須用關鍵字struct,這裡的tag可以省略,但最好不要省略
(2)這裡只是宣告了結構體型別,實際並不占用記憶體,只有定義了結構體變數,才占用記憶體
(3)結構體每個成員可以是相同或不同的型別的變數,但必須至少有乙個成員變數。
例如:描述乙個學生
struct student
;//注意,這裡的分號不能丟
2)結構體的自引用
如果乙個結構體型別中的成員變數的型別是該結構體型別,這樣做是否可以呢?如:
struct student
;
如果這樣宣告,那麼該結構體型別定義的變數大小又是多少呢,是不確定的,所以,這樣宣告是錯誤的。
正確的自引用方式:
struct student
;
不論是什麼型別的指標,在32位平台上所佔的均是4位元組,64位平台上均是8位元組,這樣,結構體變數的大小就可以確定了。
3)結構體的不完整宣告
struct a
;struct b
;
這樣寫是否可以呢,結構體struct b的定義在結構體struct a的下面,所以不可以這樣寫。那麼,將兩個結構體型別宣告的位置互換一下呢,也是不可以的,這樣,結構體struct a的定義就在結構體struct b的下面,正確的方式如下:
struct b;
struct a
;struct b
;
當結構體的定義在結構體的使用下面時,應當提前宣告,這樣,才會避免錯誤。
注意:當結構體互相包含時,應當使用結構體的不完全宣告。
4)結構體變數的定義和初始化
例如,根據上述的結構體定義結構體變數可以有下述幾種方法:
(1)結構體宣告的同時定義變數
struct student
s=;
(2)宣告結構體後再定義變數
struct student
;struct student s=;
(3)匿名結構體型別定義變數
struct
s=;
這種方法也是可以的,但最好不要這樣做,如:
struct
s;struct
*ps;
如果進行操作:ps=&s;
這樣是不可以的,編譯器會將上述兩個結構體當做不同型別的結構體,所以會發生錯誤。
注意:結構體初始化與陣列相同,都必須整體進行賦值。
5)結構體成員的訪問
結構體成員的訪問有下述兩種方法:一是通過結構體變數進行訪問,二是通過結構體指標進行訪問。
struct student
ps;struct student s=;
ps=&s;
(1)通過結構體變數進行訪問:
printf("%s\n",s.name);
(2)通過結構體指標進行訪問:
printf("%s\n",ps->name);
這兩種方法達到的效果都是相同的。
6)結構體內存對齊(重要)
先看下面兩個例子:
struct a
;struct b
;
結構體a的所佔記憶體為:12位元組。結構體b所佔記憶體為:8位元組。
兩個結構體的成員構成完全相同,除了順序不同,為什麼所佔的記憶體不同呢?這裡,就涉及到結構體的記憶體對齊問題:
結構體內存對齊規則:
(1)結構體第乙個成員變數始終在偏移量為0的位址處
(2)其他結構體成員變數的偏移量在對齊數的整數倍處。對齊數:編譯器預設的對齊數與自身型別所佔大小的最小值,vs預設為8,linux預設為4。
(3)結構體的最大小必須是最大對齊數的整數倍
(4)如果巢狀了結構體,巢狀的結構體的對齊數即為自己的最大對齊數。
通過以上規則,我們就可以明白上述兩個結果為什麼不同了。在結構體a中,第乙個成員變數偏移量為0,佔1個位元組,第二個成員變數,對齊數為4,佔4個位元組,所以從偏移量為4處開始放置4個位元組,第三個成員對齊數為1,佔乙個位元組,所以從偏移量為8處開始放置1個位元組,此時,共占用了9個位元組,但考慮到規則(3),最大對齊數為4,所以共占用12個位元組。結構體b可用相同的方法考慮得到。
注意:結構體內存對齊是拿空間來換取時間
7)結構體傳參
結構體傳參與陣列相同,統一傳送結構體指標。
2. 位段
位段的宣告與結構體是類似的,只有兩點不同:
(1)位段的成員必須是整型或字元型
(2)位段的成員名後面有乙個冒號和乙個數字
如:
struct a
;
位段a的所佔記憶體是多少呢?
首先,a是int型的,會開闢32個位元位,而變數a只占用2個位元位,然後,變數b緊接著a占用10個位元位,此時還剩餘20個位元位,而變數c需要25個位元位,而剩餘的20個位元位不夠容納,所以會在開闢乙個整型的大小,來存放變數c的25個位元位,所以,該位段共占用8個位元組。
注意:位段與結構體相比,可以節省時間,但是跨平台型比較差。
3. 列舉型別
列舉型別就是可以將其成員一一枚舉出來的,比如一周的7天,可以從周一到周天一一枚舉出來。
1)列舉型別的定義
enum weekday
;
注意:
(1)列舉型別的宣告必須使用關鍵字enum
(2)除最後乙個列舉成員無符號外,其餘用逗號分隔
(3)列舉成員都是有值的,預設從0開始,也可以賦初值,之後的成員從初值開始往後依次加1。所以,列舉成員也被稱為列舉常量
2)列舉變數的定義和賦值
列舉變數的定義與結構體類似,但賦值時只能用列舉常量進行賦值。
4)聯合(共用體)型別
共用體的特點是各個成員共用一塊記憶體空間
1)聯合型別宣告
union u
;
因為聯合體成員變數共用一塊記憶體,所以該聯合體型別所佔的記憶體為4位元組。
2)共用體變數的定義及使用
union u
un;
此時,&(un.c)和&(un.i)的結果是相同的。
因此,可以用共用體型別判斷計算機的大小端問題。
3)共用體大小的計算
共用體也需要考慮記憶體對齊問題:
(1)共用體的大小至少是最大成員的大小
(2)當最大成員的大小不是最大對齊數的整數倍時,共用體的大小要是最大對齊數的整數倍。
自定義型別
typedef型別 typedef 已有型別 新建型別 示例 typedef double area,volume typedef int number number i1 area a enum enum 列舉型別名 enum week 預設sun 0,可以比較 如果修改必須形如enum week...
自定義型別
列舉從字面意思理解就是將可能取的值一一枚舉出來,列舉型別沒有成員 可言,裡邊存放的是可能取值。列舉型別的定義 enum day enum color printf d n red printf d n green printf d n blue 執行結果 day和color都是定義的列舉型別,中的內...
自定義型別
struct tag 結構體型別 variable list 結構體變數 tag 結構體標籤 例如struct stu 特殊的宣告 匿名結構體型別 struct 省略結構體標籤 x 若不建立x,則無法使用該結構體結構體的不完全宣告struct b 不完全宣告 struct a struct b 結構...