天天看點

C語言結構體點滴

        結構的本質是c語言的一種資料抽象,通俗的說,是基本資料類型的重組。為什麼要重組呢?因為基本資料類型不夠用了。為什麼不夠用了呢?因為需要的資訊類型太多了。這是一個很大的話題。資訊本來是沒有什麼類型之分的,但是為了便于在計算機内部的管理,人們在c語言中把資訊先分成了基本的幾個類型,比如整型、浮點型、字元型、布爾型等等。但是呢,描述一個事物的全部資訊有時候僅用一種基本類型是不夠的,比如一本書的基本屬性:作者(字元型)、價格(浮點型)、出版日期(我也不知道什麼型)、書名(字元型)。然而操蛋的是,我們要處理的并非是這本書的某個屬性,而是整體,這時候我們隻好把各種類型組合起來構造一種全新的資料類型——這正是發揮我們想象力和創造力的時候。除了基本類型以外并由其組合而成的新類型統稱為結構體。

1、在c語言中,要創造一個全新的資料類型,首先要定義這麼一個類型。告訴編譯器這個新類型由哪些基本類型組成。标準的定義形式如下: 

struct book

{

    int price;

    char title[44];

};

        首先是關鍵字struct,表明這不是一個基本類型;然後是一個标記(tag),相當于給新類型起的名字,但是這個名字并非必須的,下面會談到為什麼寫上比較好;最後是新類型的成員,需要放在花括号裡面且表明基本資料類型。需要注意的是,末尾需要加上分号,因為這隻是類型定義,屬于一種聲明,聲明都要以分号結尾。類型定義并不配置設定記憶體空間,他隻是創造了一個模版,以後用這個模版定義變量的時候才真正的配置設定記憶體。

2、定義結構體變量

有了類型就可以定義變量。如:

struct book 

} a, b;

a和b被定義為struct book類型的變量,然後按照模版配置設定記憶體空間。

也可以這樣定義變量:

struct

} a; 

以上兩張形式的定義差別在于:一個有tag一個沒有。但無論哪一種都略顯臃腫,尤其是成員衆多的時候。這時,tag的作用就顯示出來了,我們可以簡化定義的形式:

struct book a, b;

注意struct不能省略,tag必須和struct一起使用,才能相當于int、float等基本類型。而沒有tag直接定義變量的形式就不能享受這種便利了。而且tag的作用并非僅限于簡化定義形式,實際上,隻有定義了tag,這個模版(新類型)才可以被反複使用(即定義變量)而不引起混淆。像下面這樣:

} *b; 

要注意兩個結構體是不同的,至少在編譯器眼裡是不同的,即使他們的成員一樣。比如 b = &a; 這是非法的。而有了tag就可以避免這樣的混淆——tag可以把成員相同的結構預設為同一種類型。

另外,不加tag的形式隻能在定義變量的時候使用,換言之,下面的類型定義(聲明)是沒有意義的:

3、初始化

可以這樣:

struct book a = {43.5, "agv"};

成員之間用逗号隔開,同時成員順序要和模版保持一緻,即類型要比對。如果成員比模版聲明的要多就會報錯;如果少于模版數量,未指定值的項目會被置為0或空;多餘的逗号不會報錯。

也可以這樣:

struct book a = {.title = "agv", .price = 43.5};

這種形式就不必按照模版的順序指派,但是要注意一點,如果這樣:

struct book = {.title = "agv", .price = 23.1, "ree"};

那麼最後title的值到底是多少?答案是“ree”,先前的會被後來的覆寫。因為title的确是在price之後的,price指派後很自然的繼續給title指派。

初始化的時候,若結構體變量是全局變量,則必須使用常量表達式初始化成員;若結構體是局部變量,則可以是變量表達式初始化成員。

4、指派

指派和初始化是不同的(多麼痛的領悟啊)!!!!!

結構體基本上沒有指派這一說,比如下面的做法是錯的:

struct book a;

a = {.title = "agv", .price = 43.5};

數組也是這麼規定的。但是結構體變量之間可以互相指派,比如:

struct book a,b;

a = b;

當然也僅止步于局部變量。

5、通路成員變量

兩個符号: . 和 ->,組合起來有三種方式。

printf("a.title\n");

struct book *b;

b = &a;

printf("b->title\n");

printf("(*b).title\n");

這裡顯然有b->title == a.title,隻不過->專門用于指針,而.用于結構變量本身罷了。

基本内容就這麼多了,以後會繼續補充。

繼續閱讀