日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

黑马程序员C语言基础(第八天)复合类型(自定义类型)(结构体)、共用体(联合体)、枚举enum、 typedef

發布時間:2025/3/20 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 黑马程序员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 結構體變量的定義和初始化

定義結構體變量的方式:

  • 先聲明結構體類型再定義變量名
  • 在聲明類型的同時定義變量
  • 直接定義結構體類型變量(無類型名)


也能直接初始化:

結構體類型和結構體變量關系:

  • 結構體類型:指定了一個結構體類型,它相當于一個模型,但其中并無具體數據,系統對之也不分配實際內存單元。
  • 結構體變量:系統根據結構體類型(內部成員狀況)為之分配空間。
//結構體類型的定義 struct stu {char name[50];int age; };//先定義類型,再定義變量(常用) struct stu s1 = { "mike", 18 };//定義類型同時定義變量 struct stu2 {char name[50];int age; }s2 = { "lily", 22 };struct {char name[50];int age; }s3 = { "yuri", 25 };

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 = 0

2)結構體指針變量做函數參數

#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 = 18

3)結構體數組名做函數參數

#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, 22

4)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是一個能在同一個存儲空間存儲不同類型數據的類型;
  • 聯合體所占的內存長度等于其最長成員的長度,也有叫做共用體;
  • 同一內存段可以用來存放幾種不同類型的成員,但每一瞬時只有一種起作用;
  • 共用體變量中起作用的成員是最后一次存放的成員,在存入一個新的成員后原有的成員的值會被覆蓋;
  • 共用體變量的地址和它的各成員的地址都是同一地址。
#include <stdio.h>//共用體也叫聯合體 union Test {unsigned char a;unsigned int b;unsigned short c; };int main() {//定義共用體變量union Test tmp;//1、所有成員的首地址是一樣的printf("%p, %p, %p\n", &(tmp.a), &(tmp.b), &(tmp.c));//00EFFC3C, 00EFFC3C, 00EFFC3C//2、共用體大小為最大成員類型的大小printf("%lu\n", sizeof(union Test));//4//3、一個成員賦值,會影響另外的成員//左邊是高位,右邊是低位//低位放低地址,高位放高地址tmp.b = 0x44332211;printf("%x\n", tmp.a); //11printf("%x\n", tmp.c); //2211tmp.a = 0x00;printf("short: %x\n", tmp.c); //2200printf("int: %x\n", tmp.b); //44332200return 0; }

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 …
#include <stdio.h>enum weekday {sun = 2, mon, tue=5, wed, thu, fri, sat };int main() {enum weekday a, b, c;//a,b,c的類型不是int,而是weekday//int a, b, c;//跟上面有什么區別嗎?a = sun;b = mon;c = wed;printf("%d,%d,%d\n", a, b, c);//2,3,6return 0; }

9.4 typedef(為一種數據類型【基本類型或自定義數據類型】定義新名字)(用于簡化輸入,也可以適當增加代碼可讀性)

typedef為C語言的關鍵字,作用是為一種數據類型(基本類型或自定義數據類型)定義一個新名字,不能創建新類型。

  • 與#define不同,typedef僅限于數據類型,而不是能是表達式或具體的值
  • #define發生在預處理,typedef發生在編譯階段
#include <stdio.h>typedef int INT; typedef char BYTE; typedef BYTE T_BYTE; typedef unsigned char UBYTE;typedef struct type {UBYTE a;INT b;T_BYTE c; }TYPE, * PTYPE;int main() {TYPE t;t.a = 254;t.b = 10;t.c = 'c';PTYPE p = &t;printf("%u, %d, %c\n", p->a, p->b, p->c);//254, 10, creturn 0; }

總結

以上是生活随笔為你收集整理的黑马程序员C语言基础(第八天)复合类型(自定义类型)(结构体)、共用体(联合体)、枚举enum、 typedef的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。