sizeof(結構體)的值

在筆試時,老是看到它定義一個結構體,要你給出這個結構體sizeof()的值。
首先,給出c語言常用類型的sizeof大小。

    printf("char: %d\n",sizeof(char));
    printf("char*: %d\n",sizeof(char*));
    printf("short: %d\n",sizeof(short));
    printf("int: %d\n",sizeof(int));
    printf("signed: %d\n",sizeof(signed));
    printf("unsigned: %d\n",sizeof(unsigned));
    printf("long: %d\n",sizeof(long));
    printf("float: %d\n",sizeof(float));
    printf("double: %d\n",sizeof(double));
輸出結果:
    char: 1
    char*: 8
    short: 2
    int: 4
    signed: 4
    unsigned: 4
    long: 4
    float: 4
    double: 8

指針大小是8個字節,是因爲我是在64位系統編譯運行的。指針的作用是指向一個地址,它的大小跟地址線多少是一致的。(1字節8位,剛接觸的時候我怎麼也記不住。一般存儲大小是指存儲字節的多少,64K內存表示能放64K個字節)

那麼筆試它考結構體的字節數是爲了考什麼?是考你對結構體數據的字節對齊和位域對齊的瞭解。大多數時候,只考到字節對齊。編譯器爲什麼要進行字節對齊,因爲某些機器對數據的存儲有要求,對結構體中的數據只能從某些固定位置開始,否則會出錯。再者,存儲的規範有利於它高效的讀取。具體爲什麼高效,計組磁盤那一張我學得不認真,有興趣的同學可以再回去看一看。

結構體數據對齊的存儲規則是這樣的。先找結構體中位數最長的數據,決定了結構體存儲時是按照最長數據的字節數爲單位存儲。舉個例子

struct test2{
    char a;
    char b;
    double c;
    char d;
};

求sizeof(test2)的值,它會先找出結構體中最長的基本數據,就是double c,它佔8位,那麼結構體分配內存時以8字節爲單位,那麼上面那個結構體的字節值是4*8=24嗎?

不是的,這裏還有第二個約定,就是前後連續出現一致的數據類型,在結構體給定的內存單位內可以連續放置,直到佔完一個單位分配下一個單位,或是沒有使用完以0補充剩餘位數。char長度爲1,前面說過,test2以8爲單位分配內存,那麼char a 和char b佔據[0,1],剩下的[2…7]則補充0。

那如果結構體中有另外一個結構體作爲成員呢,如

struct test3{
    char e;
    struct test2 a;
};

它的內存長度是不是等價於

struct test4{
    char e;
    char a;
    char b;
    double c;
    char d;
};

並不等價。sizeof(test3)=32,sizeof(test4)=24,區別在於char和struct並不是一致類型,所以test3中的char e 只能單獨佔一個單位,即8字節。

靈活的c語言告訴你,它不僅可以決定結構體內存分配的單位,還可以決定每次分配最少佔用的字節數。下面這個語句可以強行設置每次對變量分配的最少字節長度。你可以試試。

#pragma pack(n) /* n = 1, 2, 4, 8, 16 */

那麼位域對齊又是怎麼回事呢。我們常說,數據是以字節的形式佔用內存的。但有時候,我們並不需要那麼多個位。比如,這個數據出現的範圍只可能是0…3,那麼2位就足夠存儲它了,我們不需要用到c中整形的最小範圍short,即16個位。

多事的c語言給出瞭如下一種定義方式,可以一個變量僅佔用基本數據的幾個位。還是那個規則,前後一致的數據可以放在同一個單位內存裏。單位內存由最長成員數據長度決定。

struct test5{
    char a:1;
    char b:1;
    char :2;
    long c:3;
    char d:2;
};

在這裏,a和b可以佔用同一個單位內存(此時a和b佔用的是單位內存第一個字節的前兩位),所以結構體長度是12。記住,未命名的位域定義是無意義的,因爲對結構體操作時無法取到未命名的位域,所以編譯器會將它優化掉。即在上面這個結構體中(char :2;)這句是可有可無的,跟定義了一個空語句( ;)是一樣的。

如果位域定義中夾雜着數據定義呢?

struct test6{
    char a:1;
    char b:1;
    char :2;
    long c:3;
    char d:2;
    double d;
};

將位域定義看做普通的數據定義就好。具體是不是這樣,啊,a和b分配時是不是位於同一字節,我的Dev-c一調試就出錯,希望能有人實驗後來告訴我。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章