1. 程式人生 > >C語言深度解剖讀書筆記2

C語言深度解剖讀書筆記2

struct

平時我們要求函式的引數儘量不多於四個,如果函式的引數多於四個使用起開非常容易出錯(包括每個引數的意義和順序都容易弄錯),效率也會降低(與具體CPU有關)。這個時候,就可以用結構體壓縮引數個數。
空結構體多大
結構體所佔的記憶體大小是其成員記憶體之和,如果成員記憶體為0,例如:

struct student
{
}stu;

sizeof(stu)的值是多少?
在Visual C++上測試結果是1 。GCC裡計算出來為0。

柔性陣列

C99(C語言的官方標準第二版)中,結構中的最後一個元素允許是未知大小的陣列,這就叫做柔性陣列成員,但結構中的柔性陣列成員前面必須至少有一一個其他成員。柔性陣列成員允許結構中包含一個大小可變的陣列。sizeof返回的這種結構大小不包括柔性陣列的記憶體。包含柔性陣列成員的結構用malloc()函式進行記憶體的動態分配,並且分配的記憶體應該大於結構的大小,以適應柔性陣列的預期大小。
柔性陣列的使用:

typedef struct st_type
{
    int i;
    int a[0];
}type_a;

有些編譯器會報錯無法編譯可以改成:

typedef struct st_type
{
    int i;
    int a[];
}type_a;

這樣我們就可以定義一個可變長的結構體,用sizeof(type_ a) 得到的只有4,就是sizeof(i) = sizeof(int)。0個元素的陣列沒有佔用空間,而後我們可以進行變長操作了。通過如下表達式給結構體分配記憶體:

type_a *p = (type_a *)malloc(sizeof(type_a)+100*sizeof(int));

這樣我們為結構體指標p分配了一塊記憶體。用p->item[n]就能簡單地訪問可變長元素。但是這時候我們再用sizeof(¥p)測試結構體的大小,發現仍然為4。

在定義這個結構體的時候,模子的大小就已經確定不包含柔性陣列的記憶體大小。柔性陣列只是編外人員,不佔結構體的編制,只是說在使用柔性陣列時需要把它當作結構體的一個成員,僅此而已。再說得直白點,柔性陣列其實與結構體沒什麼關係,只是“掛羊頭賣狗肉”而已,算不得結構體的正式成員。

  需要說明的是:C89不支援這種東西,C99把它作為一-種特例加人了標準。但是,C99支援的而不是zeroarray,形同intitem[0],這種形式是非法的;C99支援的是incomplete type ,形同int item[],只不過有些編譯器把int item[0]作為非標準擴充套件來支援,而且在C99釋出之前已經有了這種非標準擴充套件了。C99釋出之後,有些編澤器把兩者合而為一。

  當然,上面既然用malloc函式分配了記憶體,肯定就需要用free函式來釋放記憶體:
free(p);
struct與class的區別

struct的成員預設情況下的屬性是public,而class成員的卻是private。

union

union關鍵字的用法與struct的用法非常類似。
union維護足夠的空間來放置多個數據成員中的“一種”,而不是為每一個數據成員配置空間。在union中所以的資料成員公用一個空間,同一時間只能儲存其中一個數據成員,所以的資料成員具有相同的起始地址。例如:

union StateMachine
{
    char character;
    int number;
    char *str;
    double exp;
};

一個union只配置一個足夠大的空間來容納最大長度的資料成員,以本例而言,最大長度是double型別,所以StateMachine的空間大小就是double資料型別的大小。

大小端模式對union型別資料的影響

大端模式(Big_endian):字資料的高位元組儲存在低地址中,而字資料的低位元組
則存放在高地址中。
小端模式(Little_endian):字資料的高位元組儲存在高地址中,而字資料的低字
節則存放在低地址中。
union型資料所佔的空間等於其最大的成員所佔的空間。對union型成員的存取都
從相對於該聯合體基地址的偏移量為0處開始,也就是聯合體的訪問不論對哪個變數的
存取都是從union的首地址位置開始。

如何用程式確認當前系統的儲存模式

寫一個C函式,若處理器是大端,返回0;處理器是小端,返回1。

int checkSystem()
{
    union check
    {
        int i;
        char ch;
    }c;
    c.88i = 1;
    
    return(c.ch == 1);
}

enum

列舉型別的使用方法

enum enum_type_name
{
    ENUM_CONST_1,
    ENUM_CONST_2,
    ...
    ENUM_CONST_n,   
}enum_variable_name;
列舉與#define巨集的區別

#define巨集常量是在預編譯階段進行簡單替換;列舉常量則是在編譯的時候確實其值。
一般在偵錯程式裡,可以除錯列舉常量,但是不能除錯巨集常量。
列舉可以一次定義大量相關的常量,而#define巨集一次只能定義一個。

typedef
typedef struct student
{
    //code
}Stu_st,*Stu_pst;

struct student stu1 和 Stu_st stu1——沒有區別
struct student *stu、Stu_pst 和 Stu_st *stu2——沒有區別