結構體
在Java中,我們要表示一個復合的數據類型就會使用對象去封裝。而C就有結構體。
結構體是C語言中自定義的數據類型,是一組變量的集合,有別於數組,數組僅限於同一種數據類型,而結構體可以是任何數據類型,包括數組。結構體里面的每一個變量或者數組都是結構體的成員。
下面來看看結構體的基本使用
14-18行,定義了一個名稱為Person的結構體,結構體里面有 age,money,sex 三種數據類型;
20-24行,是結構體的聲明一個名為 P 的 Person 變量,並賦值;
25-27行,是結構體的基本使用,從中可以看出的是,結構體取值的時候和Java中極為相似,都是中間 . 的形式進行取其中某個變量的值。
下面來看一下結構體指針的使用。
29-30行,定義了一個結構體指針,名為 pi,並將結構體變量 p 的地址賦值給 pi 。
32行,結構體指針的使用,既然 pi 是結構體 p 的指針,那么,取結構體那就是前面加個 * 咯,就這么簡單,照葫蘆畫瓢嘛,現在取到了結構體 p,那么去 p 里面的就簡單了,直接使用前面的方式中間加個 . 即可;
33行,則是指針結構體的另一種使用方式,直接使用 -> 就可以取里面相應的值了,比32行的方式是不是假單很多呢?
結構體的長度
結構體和結構體指針都說完了,最后來看一下結構體的長度。
長度簡單嘛,直接把里面的累加不就得了,int 和 float 都是占 4 個字節,而 char 占 1 個字節,那么就直接加起來就是 9 不就得了。
到底是不是,驗證一下就知道咯。
看,打印出來的結果是12,咦,怎么那么奇怪,難道 char 也占 4 個字節?
沒錯,就是這樣,char 也是占 4 個字節,為什么呢?因為里面的其他兩個變量的長度都是 4,那么把里面的 char 也定義成 4 個字節,這樣可以方便的指針偏移。
但這不是絕對的,同樣的代碼,執行的結果也不一樣,這和編譯器以及運行環境的不一樣,哈哈。
這里需要注意的是,雖然都是4個字節,前面也說了這樣是為了方便指針的偏移,那么自然的就想到指針的加減操作,那么我們就這樣使用行不行?
如果我要取它的money字段,那么我就這樣:printf("%f",*(p+1)); 行不行呢?不行,自己可以去嘗試一下!
最后附上結構體的三種寫法:
代碼里面注釋寫的也比較清楚了,這里就不再多說了,結構體的介紹到此結束,下面來看聯合體
聯合體:
結構體搞懂了,聯合體就簡單了。
聯合體和結構體很相似,結構體的關鍵字是 struct 而聯合體的關鍵字是 union 。看代碼:
這看起來和結構體沒什么差別嘛。沒差別就不會出現聯合體咯。所以再看下面的代碼:
接上面的代碼,第一行的打印結果是12,這個不用過多的解釋,然后當你去給聯合體中的 money 去賦值之后,你再打印一下 age 的值,你就會發現,age 的值已經完全不對了,而你再去打印一下 money 的值,你就會發現 money 的值是對的。
所以,這就是兩者的區別,結構體里面的數據是會不斷的覆蓋的,而結構體里面的數據是相互獨立的。
現在問題來了,聯合體的長度是多少呢?還是累加?累加就沒有意義了,占那么大的內存存那么少的數據是得不償失的,所以,聯合體的長度就是取該聯合體中最長的一個變量的長度。
聯合體的介紹也就到這里。
結構體和聯合體都介紹完了,最后來介紹一個枚舉,枚舉就是窮舉,也就是說,只能是這里面的值中的某一個,不可能是其他。
看看代碼:
14-17行是枚舉類型的聲明;
19行是定義並賦值;
20行是打印結果,打印的結果為什么會是int 類型的值呢?又為什么是 1 呢?
這很簡單,枚舉是窮舉,那么就是有限的,而不是無限的,既然是有限的,那么里面就會對枚舉的每一個值進行編號,像數組一樣,從0開始 編號,這就是為什么打印出來的值是int,為什么是1呢?因為Monday在枚舉中的排行是第2啊,就這么簡單。
當然,如果你不喜歡從0開始編號,也可以自定義一個初始值:
從代碼上可以看到,枚舉不僅可以自己自定義起始的值,中間也可以重新自定義,並且后面的也會依次的+1
枚舉,就先到這里。