結構體c語言運算
① c語言結構體(struct)用法詳解
C語言結構體(struct)用法詳解
在開發過程中,當一組數據包含不同數據類型時,數組無法滿足,這時就需要C語言中的結構體來處理。結構體允許每個成員擁有任意數據類型,解決了類型不一致的問題。
定義結構體類型時,用struct後面跟結構體名,如`struct stu`,這樣就創建了一個結構體類型,可以用來定義變數。注意,結構體定義結束後需要加上分號。有三種創建結構體變數的方式:
- 先定義結構體,再定義變數
- 定義結構體類型的同時聲明變數
- 直接聲明結構體變數(匿名結構體)
通過結構體成員訪問,用.運算符(對變數)或->運算符(對指針)來區別。在函數傳參時,傳遞的是結構體指針,而非先定義指針變數。
結構體初始化常用於同時定義變數並賦予初始值,先定義再初始化和常用初始化方法有所不同。在處理復雜結構體時,通常先清零所有成員,再按需填充。
結構體定義時,有時需要typedef簡化類型,如`typedef struct _stu STU;`。對於成員引用,可以使用重新定義的類型,這時可能需要前置聲明。
結構體的對齊可以通過#pragma指令指定,如`#pragma pack(2)`,確保內存以2位元組為單位對齊。對齊規則遵循2的冪次。
總結起來,學習C語言結構體對於編程非常重要,尤其是對齊和指針操作。不斷學習和實踐是提升編程技能的關鍵。對於想深入學習C/C++的朋友,可以加入學習交流群,獲取更多資源和指導,如企鵝群號763855696。
② c語言中->是什麼意思
"->"是C語言中的一個運算符:指向結構體成員運算符。常常用於結構體中
比如:
struct student{
int number;
float score;
char adrr;
}student1,*p;
int a;
p=&student1;
這上面是 定義了一個結構體變數student1;和一個指向結構體變數的指針p;
然後看下面一句:a=p->number;
意思是把p所指向的結構體變數中的number的值賦給a;這個運算符常常和指針變數和有結構體變數一塊使用。意思就是指針所指向的結構體變數中的某一個成員。
就是指向的意思;
③ C語言中結構體位元組的計算方式
在說計算方式之前先講講幾個概念一個是 偏移量 還有一個是 內存對齊 。先說偏移量,網路對於它的定義是這樣:把存儲單元的實際地址與其所在段的段地址之間的距離稱為段內偏移,也稱為「有效地址或偏移量」。在結構體裡面大概是指結構體變數中成員的地址和結構體變數地址的差。然後再說一下內存對齊這個概念:內存中存放基本類型數據時,計算機的系統會對其位置有限制,系統會要求這些數據的首地址的值是某個數的倍數,而這個數被稱為該數據類型的對齊模數。雖然ANSI C標准中沒有強制規定相鄰聲明的變數內存中要相鄰,但是編譯器會自動幫你處理這個問題,也就是相鄰變數之間可能會填充一些位元組。因此在這個問題上又有了編譯器的區別。
那我們先來講講結構體變數在微軟的編譯器的對齊吧
1.結構成員的首地址要是其最寬的基本類型成員的整數倍。編譯器在給結構體分配內存的時候先找到最寬的基本成員,然後再在內存中尋找地址,並將這個最寬的基本數據類型的大小作為對齊模數
2.結構體每一個成員相對於首地址的偏移量是成員大小的整數倍,如果沒有達到這個要求,編譯器會自動填加位元組。編譯器在為結構體成員開辟內存的時候會先檢查開辟內存的首地址與結構體變數的首地址之間的偏移量,如果是成員體的整數倍那麼就存放這個變數,不然的話就在這個成員和上一個成員之間填充位元組,以達到整數倍的目的
3.結構體所佔的總內存大小要是最大成員體大小的整數倍,如果不是,那麼編譯器會在末尾補充位元組。結構體的最後一個成員,不僅要滿足前兩條原則,最後一條准則也要滿足。
接下來來看看幾個例子。
這個結構體在VS 2017下的sizeof的運算結果是12。那麼根據上面的對其規則我們來對其進行計算。
首先是char a。char大小是1,相對於首地址的偏移量是0,然後是int i。int i的大小是4,相對於首地址的偏移量是1,但是1不是4的整數倍,所以編譯器會自動在char a和int i之間填充位元組位元組。所以in i的偏移量是4。而之後的float b大小4偏移量就是int i的偏移量加上int i的大小故float b的偏移量大小就是8,而8正好是4的倍數那麼就不會有位元組填充。而結構體的大小也就自然是最後8+4=12了
從這里也可以看出結構體大小等於最後一個成員體的大小加上它的偏移量。
那麼我們再來看一個例子
那麼我們再利用之前的演算法來對其進行運算,int i的大小是4偏移量是0,int c 的大小是4偏移量是4,double b的大小是8,偏移量是8。char a的大小是1 ,偏移量是16。那麼這個結構體的變數的大小就是16+1=17嗎?答案肯定不是這樣的。在VS的sizeof的運算下這個的結果是24,為什是24呢,那麼這之前說的最後一條原則就要用上了。結構體的大小確實是等於最後一個成員的偏移量加上最後一個成員的大小,但是如果這個結構不滿足是結構體中最大成員大小的整數倍這個條件那麼,編譯器會自動在最後填充位元組使其滿足,也就是說,雖然我們計算出的結果是17但是17並不是8的倍數,所以編譯器自動在最後填充位元組使其成為8的倍數,即自動擴充成24.、
那我們再來說一下GCC編譯器下的模式。GCC編譯器在Windows環境下用的會比較少,主要在Linux平台下使用GCC編譯器就不遵守微軟的編譯器下的一些准則了,比如之前 說過的對齊模數。微軟的編譯器下的對齊模數是結構體成員中最大的大小而在GCC編譯器下對齊模數最大隻能是4。這就意味著對齊模數只能是1,2,4中的一個。因此之前講過的在微軟編譯器下的的一些原則會有些不同。之前講過的成員的首地址的偏移量要是成員大小的整數倍在這里就有點區別了。在GCC中如果成員大小小於等數4那麼繼續按照之前的標准就好了,但如果大於4,則結構體每個成員相對於結構體首地址的偏移量只能按照是4的整數倍來進行判斷是否添加填充。來看一個簡單的例子。
在這個例子中,如果是按照微軟的編譯器的話計算的結構應該是16,但是在GCC編譯器下是12。道理就是之前講的。
雖然理論上如此但是我自己在試的時候發現上面的運算結果是16,沒錯是16而不是12!為什麼呢?難道是這個理論錯了么,當然不是。我們可以嘗試在GCC下計算一下sizeof(int *)(是int *而不是int)。你會發現結果是8(如果是sizeof(int)那麼結果結果就是4),輸出結果是8那就解決了我們的疑惑。 64位系統的對其長度默認是8而32位的才是4 。這就合理解釋了為什麼計算結果是16而不是12。
對齊模數的選擇只能是基於基本數據類型,所以對於結構體嵌套結構體就不能這么,至於其的計算方式之後再補充
④ C語言,指向結構體成員運算符是什麼意思
結構體主要成員運算符有"."和" -"多用於修改結構成員的值。以下是具體的例子struct date{ int year; int month; int day;};int main(int argc, char* argv[]){ char end; struct date today; struct date* pdate; pdate=&today; today.year=2011; today.month=2; today.day=1; printf("year = %d ",today.year); printf("month = %d ",today.month); printf("day = %d ",today.day); printf("year = %d ",pdate-year); printf("month = %d ",pdate-month); printf("day = %d ",pdate-day);}