1. 程式人生 > >C Primer Plus--結構和其他資料型別(1)

C Primer Plus--結構和其他資料型別(1)

文章目錄

結構變數 structure variable

C中struct是用來將多種資料型別組合到一起包裝成一種新的型別。建立一個struct資料型別需要:

  • 建立結構的格式或佈局
  • 宣告遵循該佈局的變數
  • 獲取對一個結構變數的各個成員(member)或者欄位(field)的訪問

建立結構宣告

struct book {
    char title[30];
    char author[30];
    int price;
};

這樣的宣告是解釋了一個標記(可以理解為別名)為bookstruct型別所包含的資料型別:一個字串陣列-書名,一個字串陣列-作者,一個int-價格,就像一個模板一樣。這樣的宣告只是聲明瞭這樣的一個數據物件,並沒有實際非配儲存空間。當使用這個資料型別時,才會分配空間:
struct book my_book;
這裡就定義了一個book

型別的struct物件,需要注意的是它裡面的資料是沒有進行預設初始化的。

定義結構宣告

struct book my_book;這個語句會使得編譯器分配空間來容納兩個陣列一個int。還可以這樣定義:



struct初始化類似於陣列的初始化:

struct book mybook = {
    "愛你就像愛生命",
    "王小波",
    29;
};

還可以指定初始化專案:

struct book book1 = {
        .author = "王小波",
        .title = "愛你就像愛生命",
        .price =
29 };

這樣初始化不需要保持順序,而且可以只初始化若干個欄位。類似於陣列的指定元素初始化,會出現值的覆蓋情況:

struct book book1 = {
	.price = 29,
    .author = "王小波",
    35
};

此時書的價格變為35。
struct結構的元素訪問可以用點運算子:

struct book {
    char title[30];
    char author[30];
    int price;
};
int main() {

    struct book mybook = {
            "愛你就像愛生命",
            "王小波",
            29.
    };
    printf("%s",mybook.title);
    return 0;
}

結構陣列

宣告結構陣列:
struct book books[20]聲明瞭一個可以容納20本書的陣列books

巢狀結構

允許一個結構的組成元素裡面包含另一種結構。

struct publishing_house {
    char name[30];
    char location[30];
};
struct book {
    struct publishing_house publishingHouse;//book這個型別包含出版社資訊結構
    char title[30];
    char author[30];
    int price;
};

int main() {

    struct book mybook = {
            {"上海文藝出版社",
             "上海"},
            "愛你就像愛生命",
            "王小波",
            29
    };
    return 0;
}

結構指標

宣告一個指向結構的指標與普通指標宣告方式差不多:
struct book * ptobook;
但是和陣列不同之處在於結構的名字並不是該結構的地址,對ptobook進行賦值時應該使用&運算子進行取地址操作:
ptobook = & my_book;

使用指標訪問結構成員

兩種方法:

  • ->運算子
    ptobook->author返回的是ptobook指向的book結構的author欄位值,是個字串陣列。
  • *運算子與.運算子結合
    (*ptobook).author也是如此。

結構用於傳參

結構用於傳參可以有三種方式:

  • 傳遞結構成員給函式
  • 傳遞結構指標給函式
  • 傳遞結構本身給函式
    需要注意的是不同於傳遞結構指標的方式中函式會操作原有結構,向函式傳遞結構本身會產生一個原有結構的拷貝,這個拷貝是一個自動變數。

不同於陣列無法互相賦值:

    struct book mybook = {
            {"上海文藝出版社",
             "上海"},
            "愛你就像愛生命",
            "Bob",
            29
    };
//    int array1[2] = {1,2};
//    int array2[2];
//    array2 = array1;//報錯:Array type 'int [2]' is not assignable array2是常量,=左邊應該是變數。陣列無法整體賦值。

    struct book the_same_book;
    the_same_book = mybook;//合法

    mybook.price = 10;

    mybook.author[0] = 'A';
    printf("my_book: %s\n",mybook.author);
    printf("the same book: %s\n",the_same_book.author);

發現這樣操作my_book裡面的所有成員都被重新拷貝了另一份,即使是陣列也被完整拷貝了。

結構也可以作為函式的返回值。

在結構中使用指標的危害

struct name {
    char firs[20];
    char last[20];
};

struct pname {
    char *first;
    char *second;
};

在上面的程式碼中,兩個struct結構中用了陣列和指標兩種方式來表明兩個字串變數。但是在指標方式中,指標沒有初始化,那麼建立的pname物件中的字串儲存位置也就不確定,很可能會造成程式的崩潰。而使用陣列方式就不用擔心,因為陣列會被分配專門的空間,不會造成修改其他正在被佔用的記憶體裡的資料。

聯合(Union)資料結構

union這種資料結構很有意思,它允許你像宣告struct那樣建立一個模板,裡面可以有各種資料型別。但是不同的是,它在某個時刻只能儲存一個模板裡的資料型別,也就是說,union是用來存放不確定資料型別的資料。

union union_ {
    int money;
    double price;
    char name;
};

這樣的一個union_某個時刻只能儲存intdoublechar三種類型其中的一個數據。使用示例:

union union_ foo;
foo.money = 1000;//將1000儲存在foo中
foo.name = 'A';//清除1000,將'A'儲存在foo中
foo.price = 100.5;//清除'A',將100.5儲存在foo中

編譯器給foo分配的空間按intdoublechar三種資料型別中所需的最大位元組數來分配以保證可以滿足可能出現的三種儲存情況。union同樣支援互相賦值及->運算子。union可以宣告struct是它可能需要儲存的資料型別。