C語言 自定義型別詳解

2022-09-24 12:48:12 字數 2508 閱讀 8835

目錄

直接上**:

struct point p1; //建立結構體時順便建立變數,分號一定不能掉

struct point p2; //單獨建立變數

struct point p3 = ; //建立變數時順便賦值

struct node n1 = };

int main()

struct是建立結構體的關鍵字,point是結構體的名字,p1為結構體point的乙個變數,x,y稱為結構體point中的成員變數,變數的建立有兩種形式,第一,可以在建立結構體時一起建立,第二,單獨建立,建立規則為型別+名稱,對於結構體的賦值,可以在建立變數的時候順便賦值,可以先建立變數再單獨賦值。結構體的訪問有兩種方式,當使用變數進行訪問時,用.(點),再選擇該變數對應的屬性;當使用指標進行訪問時,用->,再選擇對應的屬性即可。

當我們想去計算結構體占記憶體大小的時候,就需要知道結構圖記憶體對齊這一概念,我們先來看兩個例子:

struct a ;

struct b ;

int main()

結果表明,a和b兩個結構體所佔記憶體大小並不相等,但是其內部成員變數是一樣的,只是順序不一樣。造成結果不同的原因就是因為記憶體對齊,我們來介紹結構體內存對齊的規則:

1.第乙個成員在與結構體變數偏移量為0的位址處。

其他成員變數要對齊到某個數字(對齊數)的整數倍的位址處。 對齊數 = 編譯器預設的乙個對齊數 與 該成員大小的較小值。在vs編譯器中,預設對齊數是8。

結構體總大小為最大對齊數(每個成員變數都有乙個對齊數)的整數倍。

如果巢狀了結構體的情況,巢狀的結構體對齊到自己的最大對齊數的整數倍處,結構體的整 體大小就是所有最大對齊數(含巢狀結構體的對齊數)的整數倍。

從上面的結果我們大概就能猜到,為了節省空間。總的來說,主要原因有兩點:

1.平台原因:

某些硬體平台只能在特定的位址處取位址,沒有記憶體對齊,取值時可能會出錯。

2.效能原因:

對於不對齊的情況,在讀取資料時可能要讀取兩次,以下圖為例:

在乙個32位平台上,在不對齊的情況下,如果想要讀取int的4個位元組,第一次會讀取到char的乙個位元組,和int的後3個位元組(小端),需要再讀取一次,才能將int的4個位元組完全讀取出來;相比較而言,如果是在記憶體對齊的情況下,只需要讀取一次就可以把int的4個直接讀取出來。

結構體還有實現位段的能力,問題來了,什麼是位段呢?

位段的宣告和結構體是類似的,但有兩點不同:

例如:struct a

;a就是乙個位段型別,想要知道a的大小,同樣可以用sizeof來求。

拿上面的位段a來說,會先在記憶體中開闢乙個4位元組的空間,冒號後面的數字表示該成員變數所佔記憶體的大小,單位為bit,位段中的成員在記憶體中從左向右分配, 當乙個結構包含兩個位段,第二個位段成員比較大,無法容納於第乙個位段剩餘的位時,是 捨棄剩餘的位還是利用,這是不確定的。總的來說,跟結構相比,位段可以達到同樣的效果,但是可以很好的節省空間,但是有跨平台的問題存在。光說不太好理解,我們來看下圖:

當然,位段雖然比結構體更節省記憶體,但其存在跨平台問題,需要謹慎使用。

enum day//星期

;當然也可以在定義的時候賦值,例如:

enum color//顏色

;我們知道,#define可以定義常量,那為什麼要用列舉呢?

列舉的優點:

1.增加**的可讀性和可維護性

2.和#define定義的識別符號比較列舉有型別檢查,更加嚴謹。

3.使用方便,一次可以定義多個常量

既然存在,就有其存在的道理,有些時候#define更方便,有時候列舉更方便,我們要學會合理使用

union un //宣告

;union un un; //定義變數

printf("%d\n", sizeof(un)); //計算共用體的大小

聯合的成員是共用同一塊記憶體空間的,這樣乙個聯合變數的大小,至少是最大成員的大小(因為 聯合至少得有能力儲存最大的那個成員)。

union un

;union un un;

// 下面輸出的結果是一樣的嗎?

printf("%d\n", &(un.i));

printf("%d\n", &(un.c));

//下面輸出的結果是什麼?

un.i = 0x11223344;

un.c = 0x55;

printf("%程式設計客棧x\n", un.i);

從結果可以看出,i和c的位址是一樣的,因為他們共用一塊空間,當分別給i、c賦值時,後賦值的c會覆蓋之前i的部分值。

例如:union un1

;union un2

;//下面輸出的結果是什麼?

printf("%d\n", sizeof(union un1)); //8,c佔5個位元組,比i大,最大對齊數字4,需要為4的倍數,所以為8

printf("%d\n", sizeof(union un2)); //16,c佔14個位元組,最大對齊數為4,所以為16

本文標題: c語言:自定義型別詳解

本文位址: /ruanjian/c/425970.html

c語言 自定義型別

struct stu 分號不能丟 匿名結構體型別 struct x struct a 20 p p x 非法的操作,上面倆種完全是不同的宣告 struct node 結構體的自引用 struct node n1 null 直接初始化 struct node n2 null 結構體巢狀初始化 先來看下...

C語言自定義型別

在學習c語言的時候,它有很多的自定義型別,例如 結構體,列舉,聯合。這些型別在我們的日常使用的時候,或多或少的都會遇見到,下面就系統的介紹一下這幾種型別。一.結構體 1.結構體型別的宣告 通俗點來說,結構就是一些值的集合,這些值稱為成員變數,結構體的每個成員可以是不同型別的成員變數。如下所示 str...

C語言之自定義型別

結構體型別的建立struct tag stu struct class struct class1 int main 這裡編譯器會把上邊兩個宣告當作不同的型別,而且如果我們在想建立乙個相同成員的結構體class2,就必須的在main 函式前邊建立,這樣及其不方便。struct tag class i...