黑马程序员C语言基础(第八天)复合类型(自定义类型)(结构体)、共用体(联合体)、枚举enum、 typedef
黑馬程序員C語言基礎(第一天)
黑馬程序員C語言基礎(第二天)
黑馬程序員C語言基礎(第三天)
黑馬程序員C語言基礎(第四天)數據類型
黑馬程序員C語言基礎(第五天)運算符與表達式、程序流程結構、數組和字符串、函數
黑馬程序員C語言基礎(第六天)指針
黑馬程序員C語言基礎(第七天)內存管理
第八天視頻地址
文章目錄
- 9. 復合類型(自定義類型)
- 9.1 結構體
- 9.1.1 概述
- 9.1.2 結構體變量的定義和初始化
- 定義結構體變量的方式:
- 結構體類型和結構體變量關系:
- 9.1.3 結構體成員的使用
- 9.1.4 結構體數組
- 9.1.5 結構體套結構體
- 9.1.6 結構體賦值
- 9.1.7 結構體和指針
- 結構體變量的值傳遞與地址傳遞(有圖!)
- 值傳遞
- 地址傳遞(const修飾的結構體指針變量)
- 1)指向普通結構體變量的指針(棧區空間)
- 2)堆區結構體變量(malloc)
- 3)結構體套一級指針(我勒個去,什么情況下要套來套去的,調報錯調了半天!)
- 9.1.8 結構體做函數參數
- 1)結構體普通變量做函數參數
- 2)結構體指針變量做函數參數
- 3)結構體數組名做函數參數
- 4)const修飾結構體指針形參變量
- 9.2 共用體(聯合體)(主要用來測大小端)union
- 9.3 枚舉
- 不用枚舉的情況
- 使用枚舉的情況 enum
- 9.4 typedef(為一種數據類型【基本類型或自定義數據類型】定義新名字)(用于簡化輸入,也可以適當增加代碼可讀性)
9. 復合類型(自定義類型)
9.1 結構體
9.1.1 概述
數組:描述一組具有相同類型數據的有序集合,用于處理大量相同類型的數據運算。
有時我們需要將不同類型的數據組合成一個有機的整體,如:一個學生有學號/姓名/性別/年齡/地址等屬性。顯然單獨定義以上變量比較繁瑣,數據不便于管理。
C語言中給出了另一種構造數據類型——結構體。
9.1.2 結構體變量的定義和初始化
定義結構體變量的方式:
- 先聲明結構體類型再定義變量名
- 在聲明類型的同時定義變量
- 直接定義結構體類型變量(無類型名)
也能直接初始化:
結構體類型和結構體變量關系:
- 結構體類型:指定了一個結構體類型,它相當于一個模型,但其中并無具體數據,系統對之也不分配實際內存單元。
- 結構體變量:系統根據結構體類型(內部成員狀況)為之分配空間。
9.1.3 結構體成員的使用
獲取結構體屬性有多種寫法:(*p).age要加括號是因為 . 的優先級比*高
https://www.bilibili.com/video/BV1jW411K7z8/?p=43&spm_id_from=pageDriver
#include<stdio.h> #include<string.h>//結構體類型的定義 struct stu {char name[50];int age; };int main() {struct stu s1;//如果是普通變量,通過點運算符操作結構體成員strcpy(s1.name, "abc");s1.age = 18;printf("s1.name = %s, s1.age = %d\n", s1.name, s1.age);//如果是指針變量,通過->操作結構體成員strcpy((&s1)->name, "test");(&s1)->age = 22;printf("(&s1)->name = %s, (&s1)->age = %d\n", (&s1)->name, (&s1)->age);return 0; }9.1.4 結構體數組
#include <stdio.h>//統計學生成績 struct stu {int num;char name[20];char sex;float score; };int main() {//定義一個含有5個元素的結構體數組并將其初始化struct stu boy[5] = {{ 101, "Li ping", 'M', 45 },{ 102, "Zhang ping", 'M', 62.5 },{ 103, "He fang", 'F', 92.5 },{ 104, "Cheng ling", 'F', 87 },{ 105, "Wang ming", 'M', 58 } };int c = 0;float ave, s = 0;for (int i = 0; i < 5; i++){s += boy[i].score; //計算總分if (boy[i].score < 60){c += 1; //統計不及格人的分數}}//打印總分數printf("s = %f\n", s);//s = 345.000000//計算平均分數ave = s / 5;//打印平均分與不及格人數printf("average = %f count = %d\n\n", ave, c); //average = 69.000000 count = 2for (int i = 0; i < 5; i++){printf(" name = %s, score = %f\n", boy[i].name, boy[i].score);// printf(" name=%s, score=%f\n", (boy+i)->name, (boy+i)->score);}return 0; }9.1.5 結構體套結構體
#include <stdio.h>struct person {char name[20];char sex; };struct stu {int id;struct person info; };int main() {struct stu s[2] = { 1, "lily", 'F', 2, "yuri", 'M' };//這種賦值方式太不清晰了!int i = 0;for (i = 0; i < sizeof(s)/sizeof(s[0]); i++){printf("id = %d\tinfo.name=%s\tinfo.sex=%c\n", s[i].id, s[i].info.name, s[i].info.sex);//id = 1 info.name = lily info.sex = F//id = 2 info.name = yuri info.sex = M}return 0; }9.1.6 結構體賦值
#include<stdio.h> #include<string.h>//結構體類型的定義 struct stu {char name[50];int age; };int main() {struct stu s1;//如果是普通變量,通過點運算符操作結構體成員strcpy_s(s1.name, "abc");s1.age = 18;printf("s1.name = %s, s1.age = %d\n", s1.name, s1.age);//s1.name = abc, s1.age = 18//相同類型的兩個結構體變量,可以相互賦值//把s1成員變量的值拷貝給s2成員變量的內存//s1和s2只是成員變量的值一樣而已,它們還是沒有關系的兩個變量struct stu s2 = s1;//memcpy(&s2, &s1, sizeof(s1));printf("s2.name = %s, s2.age = %d\n", s2.name, s2.age);//s2.name = abc, s2.age = 18return 0; }9.1.7 結構體和指針
結構體變量的值傳遞與地址傳遞(有圖!)
值傳遞
地址傳遞(const修飾的結構體指針變量)
如果將函數的參數改成const struct Student* p,則在函數內部不能修改p指向的結構體內存空間的內容(保護原始數據,讓它只能讀不能改)
1)指向普通結構體變量的指針(棧區空間)
#include<stdio.h>//結構體類型的定義 struct stu {char name[50];int age; };int main() {struct stu s1 = { "lily", 18 };//如果是指針變量,通過->操作結構體成員struct stu* p = &s1;printf("p->name = %s, p->age=%d\n", p->name, p->age);//p->name = lily, p->age=18printf("(*p).name = %s, (*p).age=%d\n", (*p).name, (*p).age);//(*p).name = lily, (*p).age=18return 0; }2)堆區結構體變量(malloc)
#include<stdio.h> #include <string.h> #include <stdlib.h>//結構體類型的定義 struct stu {char name[50];int age; };int main() {struct stu* p = NULL;p = (struct stu*)malloc(sizeof(struct stu));//如果是指針變量,通過->操作結構體成員if (NULL!=p) {strcpy_s(p->name, "test");p->age = 22;printf("p->name = %s, p->age=%d\n", p->name, p->age);//p->name = test, p->age=22printf("(*p).name = %s, (*p).age=%d\n", (*p).name, (*p).age);//(*p).name = test, (*p).age=22free(p);p = NULL;}return 0; }3)結構體套一級指針(我勒個去,什么情況下要套來套去的,調報錯調了半天!)
#include<stdio.h> #include <string.h> #include <stdlib.h>//結構體類型的定義 struct stu {char* name; //一級指針int age; };int main() {struct stu* p = NULL;p = (struct stu*)malloc(sizeof(struct stu));if (NULL==p) {printf("malloc分配失敗!\n");return 0;}else {p->name = (char*)malloc(strlen("test") + 1);if (NULL == (p->name)) {printf("malloc分配失敗!\n");return 0;}else {//char test[] = "test";memcpy(p->name, "test", strlen("test") + 1);//strcpy_s(p->name, "test", strlen("test") + 1);//報錯啊,不知怎么回事,說第一個和第二個參數不匹配p->age = 22;printf("p->name = %s, p->age=%d\n", p->name, p->age);//p->name = test, p->age=22printf("(*p).name = %s, (*p).age=%d\n", (*p).name, (*p).age);//(*p).name = test, (*p).age=22if (p->name != NULL){free(p->name);p->name = NULL;}if (p != NULL){free(p);p = NULL;}}}return 0; }9.1.8 結構體做函數參數
1)結構體普通變量做函數參數
#include<stdio.h> #include <string.h>//結構體類型的定義 struct stu {char name[50];int age; };//函數參數為結構體普通變量 void set_stu(struct stu tmp) {strcpy_s(tmp.name, "mike");tmp.age = 18;printf("tmp.name = %s, tmp.age = %d\n", tmp.name, tmp.age); }int main() {struct stu s = { 0 };set_stu(s); //值傳遞printf("s.name = %s, s.age = %d\n", s.name, s.age);return 0; }運行結果:
tmp.name = mike, tmp.age = 18 s.name = , s.age = 02)結構體指針變量做函數參數
#include<stdio.h> #include <string.h>//結構體類型的定義 struct stu {char name[50];int age; };//函數參數為結構體指針變量 void set_stu_pro(struct stu* tmp) {strcpy_s(tmp->name, "mike");tmp->age = 18; }int main() {struct stu s = { 0 };set_stu_pro(&s); //地址傳遞printf("s.name = %s, s.age = %d\n", s.name, s.age);return 0; }運行結果:
s.name = mike, s.age = 183)結構體數組名做函數參數
#include<stdio.h>//結構體類型的定義 struct stu {char name[50];int age; };//void set_stu_pro(struct stu tmp[100], int n) //void set_stu_pro(struct stu tmp[], int n) void set_stu_pro(struct stu *tmp, int n) {int i = 0;for (i = 0; i < n; i++){sprintf(tmp->name, "name%d%d%d", i, i, i);tmp->age = 20 + i;tmp++;} }int main() {struct stu s[3] = { 0 };int i = 0;int n = sizeof(s) / sizeof(s[0]);set_stu_pro(s, n); //數組名傳遞for (i = 0; i < n; i++){printf("%s, %d\n", s[i].name, s[i].age);}return 0; }運行結果:
name000, 20 name111, 21 name222, 224)const修飾結構體指針形參變量
//結構體類型的定義 struct stu {char name[50];int age; };void fun1(struct stu * const p) {//p = NULL; //errp->age = 10; //ok }//void fun2(struct stu const* p) void fun2(const struct stu * p) {p = NULL; //ok//p->age = 10; //err }void fun3(const struct stu * const p) {//p = NULL; //err//p->age = 10; //err }9.2 共用體(聯合體)(主要用來測大小端)union
https://www.bilibili.com/video/BV1jW411K7z8/?p=57&spm_id_from=pageDriver
- 聯合union是一個能在同一個存儲空間存儲不同類型數據的類型;
- 聯合體所占的內存長度等于其最長成員的長度,也有叫做共用體;
- 同一內存段可以用來存放幾種不同類型的成員,但每一瞬時只有一種起作用;
- 共用體變量中起作用的成員是最后一次存放的成員,在存入一個新的成員后原有的成員的值會被覆蓋;
- 共用體變量的地址和它的各成員的地址都是同一地址。
9.3 枚舉
不用枚舉的情況
#include <stdio.h>#define red 1 #define green 2 #define blue 3int main() {int flag = 0;if (flag == red) {return 0;}else if (flag == green) {return 1;}else if (flag == blue) {return 2;}return 0; }這樣的缺點就是flag一多的話,就要寫好多個
使用枚舉的情況 enum
枚舉:將變量的值一一列舉出來,變量的值只限于列舉出來的值的范圍內。
枚舉類型定義:
enum 枚舉名 {枚舉值表 };- 在枚舉值表中應列出所有可用值,也稱為枚舉元素。
- 枚舉值是常量,不能在程序中用賦值語句再對它賦值。
- 舉元素本身由系統定義了一個表示序號的數值從0開始順序定義為0,1,2 …
9.4 typedef(為一種數據類型【基本類型或自定義數據類型】定義新名字)(用于簡化輸入,也可以適當增加代碼可讀性)
typedef為C語言的關鍵字,作用是為一種數據類型(基本類型或自定義數據類型)定義一個新名字,不能創建新類型。
- 與#define不同,typedef僅限于數據類型,而不是能是表達式或具體的值
- #define發生在預處理,typedef發生在編譯階段
總結
以上是生活随笔為你收集整理的黑马程序员C语言基础(第八天)复合类型(自定义类型)(结构体)、共用体(联合体)、枚举enum、 typedef的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 黑马程序员C语言基础(第七天)内存管理
- 下一篇: visual studio如何更改启动项