C語言入門(十九)之結構體
太晚了(11點半了),明天繼續結構體
陣列: 是用於儲存一組相同型別的資料
結構體: 是用於儲存一組不同型別的資料
// 1.定義結構體型別 struct Person { // char name[20]; char *name; int age; double height; }; // 2.定義結構體變數 // int num; struct Person p; // 注意: 陣列不能先定義再進行一次性的初始化, 所有下面的寫法是錯誤的 // p.name = "lnj"; // name = {'l', 'n', 'j', '\0'}; // 可以使用 結構體變數名稱.屬性的方式給結構體變數賦值 p.name = "lnj"; p.age = 30; p.height = 1.75;
結構體的初始化
struct Dog { char *name; int age; double height; }; // 1.定義的同時初始化 struct Dog sd = {"wc", 13, 5.0}; // 2.先定義再初始化(逐個初始化) struct Dog sd1; sd1.name = "ww"; sd1.age = 5; sd1.height = 10.9; // 3.先定義再初始化(一次性初始化) struct Dog sd2; // 特別注意: 結構體和陣列有一點區別, 陣列不能先定義再進行一次性的初始化, 而結構體可以 // 只不過需要明確的告訴系統{}中是一個結構體 sd2 = (struct Dog){"xq", 8, 8.8}; // 陣列? 結構體? // 4.指定將資料賦值給指定的屬性 struct Dog sd3 = {.height = 1.77, .name = "ww", .age = 33}; printf("name = %s, age = %i, height = %lf\n", sd3.name, sd3.age, sd3.height);
結構體如何開闢儲存空間
其實結構體分配儲存空間本質上並不是將所有屬性佔用的儲存空間的總和加在一起後再分配。
而是會獲取結構體型別中佔用記憶體最大的屬性的大小, 然後取該大小的倍數。
如果剩餘的儲存空間"不夠"儲存將要儲存的資料, 那麼就會重新開闢8個位元組的儲存空間, 並且將需要儲存的資料放到新開闢的儲存空間中。
如果剩餘的儲存空間"夠"儲存將要儲存的資料, 那麼就不會開闢了。
struct Person{ // double height; // 8 int age; // 4 // int heigth; // 4 double height; // 8 char c; // 1 // char *name; // 8 }; struct Person sp; printf("size = %lu\n", sizeof(sp));
輸出:
size = 24
結構體定義的形式
1.先定義結構體型別, 在定義結構體變數
struct Person
{
int age;
char *name;
double height;
};
struct Person sp;
2.定義結構體型別的同時定義結構體變數
struct Person
{
int age;
char *name;
double height;
} sp;
3.定義結構體型別的同時定義結構體變數, 並且省略結構體名稱
弊端: 由於結構體型別沒有名稱, 所以以後就不能使用該結構體型別
優點: 如果結構體型別只需要使用一次, 那麼可以使用該方式
struct
{
int age;
char *name;
double height;
} sp;
結構體型別的作用域
如果將結構體型別寫在函式或者程式碼塊外面, 那麼結構體型別的作用域和全域性變數一樣, 從定義的那一行開始一直直到檔案末尾。相同作用域不能有同名的結構體型別。
在不同的作用域中可以定義同名的結構體型別 , 如果使用同名的結構體型別定義結構體變數, 採用就近原則。
如果結構體定義在函式或者程式碼塊中, 那麼結構體型別的作用域和變數的作用域一樣, 從定義的那一行開始, 一直到函式結束或者到程式碼塊結束。
指向結構體的指標
當指標指向結構體之後如何利用指標訪問結構體
結構體變數名稱.屬性;
(*結構體指標變數名稱).屬性;
結構體指標變數名稱->屬性;
struct Person
{
int age;
char *name;
double height;
};
struct Person sp = {30, "lnj", 1.75};
sp.name = "lnj";
sp.age = 30;
sp.height = 1.75;
// 定義了一個指向結構體的指標
// *sip == sp
struct Person *sip;
sip = &sp;
// 注意: 報錯的原因是因為.運算子的優先順序比*高
(*sip).name = "xxx";
(*sip).age = 88;
(*sip).height = 1.95;
printf("age = %i, name = %s, height = %lf\n", (*sip).age, (*sip).name, (*sip).height);
sip->age = 99;
sip->name = "oooo";
sip->height = 2.1;
printf("age = %i, name = %s, height = %lf\n", sip->age, sip->name, sip->height);
結構體陣列
// 要求定義變數儲存公司中所有部門的績效
struct Bumen
{
char *name;
int count;
double kpi;
};
struct Bumen ios = {"iOS", 20, 100.0};
struct Bumen andorid = {"Andoird", 10, 99.0};
struct Bumen php = {"php", 500, 88.0};
// 元素型別 陣列名稱[元素個數];
struct Bumen bumens[3] =
{
{"iOS", 20, 100.0}, // 0
{"Andoird", 10, 99.0},
{"php", 500, 88.0}
};
// bumens[0] == ios
bumens[0].name = "iOSv587";
bumens[0].count = 99;
bumens[0].kpi = 100.0;
printf("name = %s, count = %i, kpi = %lf\n", bumens[0].name, bumens[0].count, bumens[0].kpi);
結構體巢狀
如果結構體的屬性又是一個結構體, 那麼可以通過連續.的方式, 訪問結構體屬性中的屬性。
如果結構體型別中的屬性又是一個結構體, 那麼賦值時候通過{}賦值。
struct Person
{
int age;
char *name;
// 出生日期
struct Date birth;
// 出生時間
// struct Date time;
// struct Time shic;
// 小學入學時間
struct Date ruxue;
// 小學畢業時間
struct Date biye;
// ....
};
struct Person sp =
{
30,
"lnj",
{
1980,
1,
15,
{
15,
12,
8
}
},
{
1990,
6,
9
},
{
1996,
9,
5
}
};
結構體與函式
#include <stdio.h>
struct Person
{
int age;
char *name;
};
void change(struct Person *p);
int main(int argc, const char * argv[]) {
struct Person sp1 = {30, "lnj"};
printf("sp1.age = %i\n", sp1.age);
change(&sp1);
printf("sp1.age = %i\n", sp1.age);
return 0;
}
void change(struct Person *p)
{
p->age = 998;
}
輸出:
sp1.age = 30
sp1.age = 998