C語言結構體與聯合體
聯合體
C語言的聯合體union又叫做共用體,並不常用,類似於大家所熟知的結構體struct。如其名,我們差不多能獲知這個資料結構有一部分東西是共用的,結構裡面除了變數空間,也沒什麼可以共用的了。即,共用體內部所有宣告的變數,均為共用一個記憶體首址,聯合體佔用記憶體大小與聯合體內部佔用空間最大的變數相同。我們給其中每一個變數進行的賦值,都會影響到其他變數的值。下面直接砍一刀關於聯合體的選擇題。
#include stdio.h; int main() { union { short int a[2]; long b; char c[4]; }s; s.a[0]=0x39; s.a[1]=0x38; printf("%lx %c\n",s.b,s.c[0]);
}
所以上面那道題的輸出結果是?
3839 39?不對。
380039 39?不對。
答案是: 380039 9。 有點懵。
現在開始分析一下這道題,意圖很明顯,要考察聯合體以及printf輸出的格式符兩個點。
short int 每個佔兩位元組,兩個四位元組;long 佔四位元組;char 每個佔一位元組,四個佔四位元組。因此這三個變數所佔據的記憶體空間大小一致,畫了個草圖如下:
因此在對s.a進行賦值之後,聯合體內部資料使用16進製表示為:
0x 0038 0039。而此時還應該注意的是char c[0]中存的是0x39,列印的是%c,即字元,所以打印出的字元不是0x39,而是0x39指向的ASCII碼,即0x39=57,57對應字元9。所以,這道題打印出的結果是:
380039 9 。
結構體
關於C的結構體,我覺得我理解的還是不夠深入,直接看一道題。
`#include <stdio.h> #include <string.h> struct A { int a; char b [10];double c; }; void f(struct A t); int main() { struct A a={1001,"zhang",1908}; f(a); printf("%d,%s,%6.1f\n",a.a,a.b,a.c); return 1; } void f(struct A t) { t.a=1002;strcpy(t.b,"chang"); t.c=1201; }
進行過這樣一番操作之後,結構體A的內容並沒有變化,輸出的結果與之前相同。這就讓我當時覺得很費解的一個問題,為什麼我傳遞進去結構體,而且修改了值,卻實際內容沒有變化?
其實,我在這裡陷入了一個僵化的思維,在學習c之後,我接觸了java,這段程式碼中的結構體,在java裡面被視為內部類的存在,而A a相當於面向物件新建的物件,若是在java裡面,物件作為函式的實參,此時傳遞的相當於物件的指標,指標在java中簡化了。這樣,函式中對形參物件的任何改變都會與實參同步改變。但需要注意的是,這裡不是java,struct也不是物件。c語言中struct作為函式形參時,依舊是作為實參的一個副本,副本在子函式中再怎麼改變,只要不return值,就不會影響到實參的值。
指標的形參實參
這樣根據上個題,就會想到通過函式引數傳遞,進行兩個數交換的demo。使用的原理就是函式引數為指標,對兩個指標中的資料內容進行交換,從而達到交換實參中的資料的目的。
正確的例子
`void fun(int *p,int *q) { int a; a = *p; *p = *q; *q = a; }
錯誤的例子
`void fun(int *p,int *q) { int *a; a = p; p = q; q = a; } 要注意的是,形參始終只是實參的一個副本,形參本身的變化,無法對實參的值造成影響。指標型別的形參與實參雖然不是一個變數, 但指向同一個地址;第一個函式,對形參指向的地址進行了數值變化;第二個函式,只是對形參的指向作了修改。 # 結語 這些相關的題和知識都是計算機二級的很基礎的計算機知識,我到現在卻還需要重新複習一遍,學習態度是個問題。