C語言小結之結構體

2021-08-16 06:24:37 字數 3594 閱讀 9955

一、什麼是結構體?

結構體也叫結構,是由一系列具有相同型別或不同型別的資料構成的資料集合。

二、結構體的宣告

struct tag

variable_list;

//比如描述乙個學生

struct stu

;//分號不可以丟掉,切記!!!

特殊的宣告:結構體在宣告的時候可以不完全宣告,比如:

struct

x;struct

a[20], *p;

以上兩個結構體在宣告的時候都省略了結構體的標籤(tag)。

如果在這個時候,將結構體x的位址賦值給結構體指標p會發生什麼呢?

在linux平台下顯示,型別不匹配,也就是說原本想表達的意思用乙個結構體定義兩個變數,但是由於未加標籤,系統認為這兩個不是相同的型別,所以在進行賦值的時候系統會出現警告。所以在我們使用結構體的時候盡量不要省略掉結構體標籤,方便自己,也方便別人。

三、結構體的成員

結構體的成員可以是標量、陣列、指標,甚至是其他結構體 。

訪問:結構體標量訪問成員是通過點操作符(.)訪問的。點操作符接受兩個運算元。例如:

struct stu

;struct stu s;//定義結構體變數

我們可以看到s有成員name和age兩個成員,在訪問s成員時就可以用點操作符。

struct stu s;

strcpy(s.name,"xiaoming");

s.age = 20;//訪問結構體成員

當我們得到的不是乙個結構體變數,而是乙個結構體指標的時候那該如何訪問結構體成員呢?

struct stu 

s;void print(struct s *ps)

我們可以觀察到,在我們得到的是結構體指標的時候,對結構體內成員訪問有兩種方法,一種是解引用指標以後跟上面的訪問方式相同利用點操作符進行訪問;另外一種方法就是用指標加->指向結構體內成員直接進行訪問。

四、結構體的自引用

大家都知道在陣列裡面可以有二維陣列,也就是說乙個陣列裡面的元素還是乙個陣列,那麼結構體的裡面是否可以放置乙個結構體呢?或者說是結構體成員裡面是否可以 包含自己本身呢?

這裡編譯器裡面有個警告,意思是**中並沒有有效**,但是顯而易見,結構體內放置結構體時候可以的。這時候我們再做乙個測試。

我們發現當結構體自己引用自己的時候是不行的。但是結構體在引用自己的時候可以指標的形式引用自己,如:

struct test

;

再比如兩個結構體之間是否能夠相互包含?

struct a

;struct b

;

經過實踐發現,在不同編譯器下有不同的結果,在這裡建議大家在結構體互相包含的時候,應該提前宣告一下。

struct b;

struct a

;struct b

;

五、結構體變數的定義和初始化

我們知道結構體就是一種型別,跟整形、字元型、浮點型一樣,那麼該如何定義這個型別的變數以及如何初始化呢?

struct point

p1;//宣告結構體型別的同時定義結構體變數p1

struct point p2;//定義結構體變數

struct point p3 = ;//定義結構體變數p3的同時對其進行初始化賦值

結構體的初始化與陣列初始化的時候是一樣的。

六、結構體的記憶體對齊問題

我們在進行對結構體使用的時候有沒有想過結構體的大小問題?

同樣的**我們換個順序呢?

怎麼僅僅是換了個順序結構體的大小就不同了?

其實結構體再設計的時候有一些的對齊規則:

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

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

結構體的總大小為最大對齊數的整數倍

如果巢狀結構體的話,巢狀的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數的整數倍。

但是為什麼要存在這些規則呢?

1.不是所有平台都能訪問任意位址上的任意資料的;某些平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常。

2.為了訪問未對齊的記憶體,處理器需要作兩次記憶體訪問;而對齊的記憶體訪問僅需要一次訪問。

總體來說結構體的記憶體對齊是拿空間來換取時間的做法,增加了訪問效率。在設計結構體的時候,我們既要滿足記憶體對齊,又要節省空間,所以我們盡量讓占用空間小的成員集中在一起。

七、結構體的傳參問題

先來看兩個例子;

struct s

;struct s s =

,1000};

void

print1(structss)

void

print1(struct

s* s)

intmain()

我們分別呼叫這兩個print函式,檢視其執行時間;

發現在給print函式傳參的時候,對函式傳結構體的名字所執行的速度比直接傳結構體位址執行的速度慢了一倍之多。原因是:在呼叫函式的時候,需要傳參,而在傳參的時候引數需要壓棧,如果在傳乙個結構體物件的時候,結構體過大,引數壓棧的系統開銷也很大,這樣的話就會降低效能,所以效率變低,而直接傳結構體的位址就不會影響效能,所以在結構體傳參的時候傳結構體位址。

c語言小結 結構體

一 宣告結構的形式 1.標準格式 struct message 2.typedef的妙用 參見利用typedef簡化結構體的使用 二 結構體的初始化 1.初始化格式 1.struct message bank 2.struct message bank 2.對結構體內物件的訪問參見 兩種訪問物件的方...

C語言 C 結構體疑問小結

1.關於結構體 情況一 最簡單的結構體定義struct stu 關鍵字 struct 表明這是在定義乙個結構體,stu是這種資料格式的名稱,因此我們可以像使用char int等建立變數一樣使用stu建立stu型別的變數了。情況二 附加 結構體變數 的初始化的結構體定義 struct stushenq...

c語言結構體之結構體巢狀

注意 1結構體內部再次定義乙個結構體 但是沒有建立結構體的例項 也就是說再次定義的結構體內部的變數會被當做母結構體的成員變數 1 struct tianchao 2 11 12 13 void mainww 14 24 25 struct tianchao 26 b1 內部定義的第一種方式 35 s...