首頁 > 軟體

C語言資料型別與sizeof關鍵字

2022-04-14 16:01:08

一、前言

大家好,歡迎來到C語言深度解析專欄—C語言關鍵字詳解第三篇,在本篇中我們將會介紹C語言當中的資料型別,並由此引出C語言當中的另外一個重要的關鍵字 — sizeof .

第一篇:C語言 auto和register關鍵字

第二篇:全面瞭解C語言 static 關鍵字

二、資料型別

1、資料型別有哪些

C語言的資料型別包括基本型別(內建型別)、構造型別(自定義型別)、指標型別以及空型別

2、為什麼要有資料型別

為什麼要有內建型別

我們日常生活中會遇到各種各樣的場景,而不同的場景需要不同資料來表示,比如我們聚餐的人數、天氣的溫度、海拔的高度等事情通常用整數來描述,而像人的身高、廣播的頻率、商品的價格則通常用小數表示,又比如我們的車牌號、樓棟的命名、服裝的尺碼則需要要用字母來表示;C語言作為第一門高階程式設計語言,為了能準確描述我們生活中各種各樣的場景,就有了整形、浮點型、字元型這些內建型別。

為什麼要有自定義型別

我們以自定義型別中的陣列型別和結構體型別舉例:
陣列型別:我們生活中會碰到許多相同型別的集合,比如一個學校學生的學號,每一個學生的學號都是整形,那麼為了表示所有學生的學號,就勢必要定義幾千個整形,顯然,那樣太麻煩了,於是就產生了陣列型別,一個陣列裡面的每個元素的型別都是相同的,我們在定義一個學校學生的學號時,只需要定義一個有幾千個元素大小的陣列即可,而不必去慢慢定義一千個整形
結構體型別:我們生活中所要描述的物件常常是複雜資料型別的集合,拿人來說,一個人有姓名、性別、身高、體重、年齡等等,這些資料型別都是不同的,那麼為了能夠系統的描述一個人的屬性,就產生了結構體型別,它把一個人不同型別的資料都集中到一個新的型別當中,使物件描述和使用更加方便。

3、如何看待資料型別

從前面的部落格中我們知道,定義變數的本質是在記憶體中開闢一塊空間,用來存放資料,而今天我們知道不同的變數是需要定義為不同的型別的,把二者結合起來,我們就不難得出:型別決定的是變數開闢空間的大小。
這時有兩個疑問點,第一、為什麼要根據型別來開闢空間,我們直接開闢一塊空間,將記憶體整體使用不好嗎?答案是:不好。

原因主要有兩點:

1、在任何時刻,你的電腦都不是隻在執行你目前所使用的那個程式,還有其他許多的程式也在同時執行,如果把整塊都分配給了你目前執行的程式,其他程式就崩潰了。
2、即使把整塊記憶體都分配給你,你也不能保證在任何時刻都對該記憶體塊全部都用完,這樣就會導致記憶體的浪費。
第二、我們使用部分記憶體,使用多少由什麼決定的?答案是:是由你的場景決定,你的計算場景,決定了你使用什麼型別的變數進行計算。你所使用的型別,決定了你開闢多少位元組的空間大小。這也是為什麼C語言要有這麼多的資料型別,就是為了滿足不同的計算場景。
最後,那麼不同的資料型別到底在記憶體開闢多少空間呢?這就需要使用我們的關鍵字 – sizeof 來計算了。

三、sizeof – 計算不同型別變數開闢空間的大小

1、內建型別開闢的空間大小

`#include<stdio.h>
int main()
{
    printf("%dn", sizeof(char));       //1
    printf("%dn", sizeof(short));      //2
    printf("%dn", sizeof(int));        //4
    printf("%dn", sizeof(long));       //4
    printf("%dn", sizeof(long long));  //8
    printf("%dn", sizeof(float));      //4
    printf("%dn", sizeof(double));     //8
}`

2、自定義型別開闢的空間大小

陣列大小

#include<stdio.h>
int main()
{
    int arr1[10] = { 0 };       //40
    char arr2[10] = { 0 };      //10
    long int arr3[10] = { 0 };  //40
    long long arr4[10] = { 0 }; //80
    float arr5[10] = { 0 };     //40
    double arr6[10] = { 0 };    //80
    printf("%dn", sizeof(arr1));
    printf("%dn", sizeof(arr2));
    printf("%dn", sizeof(arr3));
    printf("%dn", sizeof(arr4));
    printf("%dn", sizeof(arr5));
    printf("%dn", sizeof(arr6));
    return 0;
}

從上面的結果我們很容易得出:陣列的大小 = 陣列元素的型別乘以元素個數

其他自定義型別的大小

#include<stdio.h>
struct Test1{
    int a;
    char b;
    float c;
    double d;
};
union Test2{
    int m;
    char n;
};
enum Test3 {
    monday,
    tuesday,
    wednesday,
    thursday,
    frifay
};
int main()
{
    struct Test1 test1 = { 0 };
    union Test2 test2 = { 0 };
    enum Test3 test3;
    printf("%dn", sizeof(test1));   //24
    printf("%dn", sizeof(test2));   //4
    printf("%dn", sizeof(test3));   //4
}

想必上面的結果與一些小夥伴心中的結果有所不同,確實,結構體、聯合體、列舉這些自定義型別的大小和陣列大小的求法是不相同的,其具體的求法涉及記憶體對齊、大小端、記憶體分配等相關知識,這些知識比較複雜,我會放在自定義型別詳解模組中為大家講解,現在大家不用去深究。

3、指標型別開闢的空間大小

大家可以看到,我們上面不管指標的型別是什麼(整形、字元型、浮點型、陣列型),指標的大小始終是四個位元組或者八個位元組(第一張圖X86表示32位元平臺,結果為4,第二張圖X64表示64位元平臺,結果為8),所以結論就是:指標在32位元平臺下是4個位元組,在64位元平臺下是8個位元組。(至於為什麼是這樣,這涉及到記憶體編址、地址線等相關知識,這一部分我會放在指標那裡來詳細講解,現在大家只需要記住這個結論即可)
注:第二張圖有警告是因為我的電腦是32位元平臺的,強制轉成64位元會發生大小不匹配的問題。

4、空型別開闢的空間大小

我們可以看到雖然這裡編譯器報錯了,但它仍然列印出來了void的大小:0個位元組
注:void型別的大小為0個位元組,這僅僅是在visual studio這個編譯器下執行的結果,但是,這個結果在不同的編環境下跑出來可能不同,就比如在Linux環境下,void型別的大小就為1,(由於水平的限制,這裡暫時不能為大家演示);而導致這兩者之間有差異的根本原因是不同編譯環境對C語言的支援程度不同。

四、對sizeof 的進一步理解

1、sizeof 為什麼不是函數

從上面我們可以看到,我們可以用 sizeof(a) 和 sizeof(int) 求一個整形的大小,這種方式也是大家所熟悉的,但是我們發現直接用
sizeof a 也能求出a的大小,而不需要圓括號,所以說,sizeof 是關鍵字(操作符)但是不是函數,因為函數引數需要用 () 起來才能正常使用。
注:sizeof int 報錯是因為 sizeof 和 int 都是關鍵字,而不能用一個關鍵字去求另一個關鍵字的大小

2、sizeof 的其他使用

這裡我們定義了一個整型變數 a 和 指標變數 p ,以及陣列 arr,可以看到 a 的大小為 4,arr 的大小為40,這些我們都理解,
那麼剩下的sizeof § 、sizeof(&arr) 、sizeof(arr) / sizeof(arr[0]) 是什麼意思呢?下面為大家解釋(涉及指標相關知識)

p 是一個指標變數,裡面存放的是 a 的地址,arr陣列名錶示arr陣列首元素的地址(記憶),&arr 表示取出整個陣列的地址,相當於一個陣列指標,所以sizeof§ 和 sizeof(&arr) 都是求的指標的大小,而在上面我們知道,指標在32位元平臺下是4個位元組,所以這裡結果為4。
最後,sizeof(arr) 求整個陣列的大小,sizeof(arr[0]) 求第一個元素的大小,所以二者相除得到的是陣列的元素個數10。
注:這裡用sizeof(arr[0]) 來求一個陣列元素的大小,而不是用arr[1] 、arr[2] 是因為我們不知道陣列有幾個元素,所以可能arr[1] 、arr[2] 根本不存在,但是隻要定義了陣列,那麼arr[0] 就是一定是存在的,也就是說,這樣做是為了安全。

到此這篇關於C語言資料型別與sizeof關鍵字的文章就介紹到這了,更多相關C語言 sizeof關鍵字內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com