自定義型別

2021-08-16 09:59:04 字數 4178 閱讀 5773

下面列舉幾種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 結構...