一、結構體的定義和使用
char* 不算基本數據類型
結構體(struct)是什麼
結構體:把不同類型的數據組合成一個整體。
struct Person {
char name[20];
int age;
float height;
};
struct Person是類型名- 裏面的
name / age / height是成員
結構體本身不佔內存,只是定義了一種類型。
方式一
#define _CRT_SECURE_NO_WARNINGS // windows 加上這個 抑制警告!否則不能運行
#include <stdio.h>
#include <string.h>
// 方式一
struct Worker{ // 定義一個結構體,相當於java的class
char name[10];
int age;
double salary;
};
// 結構體的定義和使用
int main() {
// struct Worker w1; 不初始化的時候,裏面的值是隨機的垃圾值
struct Worker w1 = { "xaye", 18, 5000.5 }; // 定義並初始化結構體變量
// 賦值
w1.age = 28;
strcpy(w1.name, "zhangsan");
// 方式一 賦值 // name=zhangsan, age=28, salary=5000.50
printf("name=%s, age=%d, salary=%.2f\n", w1.name, w1.age, w1.salary);
return 0;
}
方式二
#define _CRT_SECURE_NO_WARNINGS // windows 加上這個 抑制警告!否則不能運行
#include <stdio.h>
#include <string.h>
// 方式二 , 這種方式會有一個默認初始值
struct Worker { // 定義一個結構體,相當於java的class
char name[10]; // 默認 ""
int age;
double salary; // 默認 0.00
} jack;
// 結構體的定義和使用
int main() {
// 賦值
jack.age = 28;
strcpy(jack.name, "zhangsan");
// 方式二 賦值 // name=zhangsan, age=28, salary=0.00
printf("name=%s, age=%d, salary=%.2f\n", jack.name, jack.age, jack.salary);
return 0;
}
方式三
#define _CRT_SECURE_NO_WARNINGS // windows 加上這個 抑制警告!否則不能運行
#include <stdio.h>
#include <string.h>
struct Work{
char name[10];
char grade[10];
};
// 方式三,結構體嵌套
struct Worker{ // 定義一個結構體,相當於java的class
char name[10];
int age;
double salary;
Work work;
};
int main() {
struct Worker w1 = { "xaye", 18, 5000.5, {"engineer", "A"} }; // 定義並初始化結構體變量
// name=xaye, age=18, salary=5000.50, work_name=engineer, work_grade=A
printf("name=%s, age=%d, salary=%.2f, work_name=%s, work_grade=%s\n",
w1.name, w1.age, w1.salary, w1.work.name, w1.work.grade);
return 0;
}
方式四
#define _CRT_SECURE_NO_WARNINGS // windows 加上這個 抑制警告!否則不能運行
#include <stdio.h>
#include <string.h>
// 方式三,結構體嵌套
struct Worker{ // 定義一個結構體,相當於java的class
char name[10];
int age;
double salary;
struct Work {
char name[10];
char grade[10];
};
Work work;
};
int main() {
struct Worker w1 = { "xaye", 18, 5000.5, {"engineer", "A"} }; // 定義並初始化結構體變量
// name=xaye, age=18, salary=5000.50, work_name=engineer, work_grade=A
printf("name=%s, age=%d, salary=%.2f, work_name=%s, work_grade=%s\n",
w1.name, w1.age, w1.salary, w1.work.name, w1.work.grade);
return 0;
}
二、結構體指針和動態內存開闢
為什麼要用結構體指針?
- 結構體可能很大
- 函數傳參時避免拷貝
- 動態內存分配只能返回指針
|
情況
|
用法
|
|
結構體變量
|
|
|
結構體指針
|
|
結構體 + 動態內存開闢
Person *p = (Person *)malloc(sizeof(Person));
malloc返回的是void *sizeof(Person),不是sizeof(Person *)
示例:
#define _CRT_SECURE_NO_WARNINGS // windows 加上這個 抑制警告!否則不能運行
#include <stdio.h>
#include <string.h>
#include <cstdlib>
struct Worker{ // 定義一個結構體,相當於java的class
char name[10];
int age;
double salary;
};
// 結構體指針和動態內存開闢
// 示例一
//int main() {
// struct Worker worker = { "xaye", 18, 5000.5 }; // 定義並初始化結構體變量
//
// struct Worker* pWorker = &worker; // 定義結構體指針,並指向worker變量
//
// // 通過指針訪問結構體成員
// pWorker->age = 28; // 修改年齡
// pWorker->salary = 6000.0; // 修改薪水
// pWorker->name[0] = 'X'; // 修改名字的首字母
//
// // name=Xaye, age=28, salary=6000.00
// printf("name=%s, age=%d, salary=%.2f\n", pWorker->name, pWorker->age, pWorker->salary);
// free(pWorker);
//}
// 示例二
int main() {
struct Worker* pWorker;
//pWorker->age = 30; // 未初始化指針,訪問會出錯
pWorker = (struct Worker*)malloc(sizeof(struct Worker)); // 動態分配內存
pWorker->age = 27;
// age=27
printf("age=%d\n", pWorker->age);
free(pWorker);
return 0;
}
三、結構體數組
數組裏每個元素都是一個結構體
定義
typedef struct {
char name[20];
int age;
} Person;
定義結構體數組
Person arr[3];
內存佈局是連續的:
arr[0] | arr[1] | arr[2]
每一格都是一個 Person
使用
訪問成員
arr[0].age = 18;
strcpy(arr[1].name, "Tom");
結構體數組和指針的關係
數組名本質是指針
Person arr[3];
Person *p = arr; // 等價於 &arr[0]
所以:
p[1].age = 30; // 合法
(*(p + 1)).age = 30; // 等價
因此:
arr[i].age == (arr + i)->age
注意:arr[i]->age 等價於 (arr[i])->age,arr[i]是一個結構體變量本身,不是指針,所以不能用 -> ,arr + i 類型是 Person *,所以它可以用 ->,這是一個比較迷的地方。