1. 程式人生 > >C語言結構體與聯合體

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;
    }

       要注意的是,形參始終只是實參的一個副本,形參本身的變化,無法對實參的值造成影響。指標型別的形參與實參雖然不是一個變數, 但指向同一個地址;第一個函式,對形參指向的地址進行了數值變化;第二個函式,只是對形參的指向作了修改。

# 結語

       這些相關的題和知識都是計算機二級的很基礎的計算機知識,我到現在卻還需要重新複習一遍,學習態度是個問題。