(八)C語言之結構

今天來說一下C語言里的結構體(struct)、共用體(l聯合體)union、枚舉。

(一)結構體:struct

1.1 概念

  • 是一種自定義的數據類型
  • 結構體是構造類型的一種
  • 不同數據類型的集合
  • 地址空間連續,每次分配最大數據類型的寬度
  • 占用內存為所有變量的總大小(注意字節對齊問題)

1.2 定義

1.先定義結構體類型,再說明結構體變量

struct stu
{char *name;  //姓名int num;  //學號int age;  //年齡float score;  //成績
};
struct stu  student;

上面的程序使用strcuct關鍵字定義了一個結構體名為stu的結構體類型。和定義變量一樣,聲明一個結構體類型變量可以使用:數據類型 變量名 的形式。
struct stu student表示定義了一個變量名為stduent,類型為stu的結構體。該結構體含有4個成員:name、num、age、score
注意大括號后面的分號;不能少,這是一條完整的語句。
2.定義結構體類型的同時定義結構體變量

struct stu
{char *name;  //姓名int num;  //學號int age;  //年齡float score;  //成績
}student;

在定義時直接聲明結構體變量,只需要將結構體變量名放在花括號后面,并加上分號即可。
3.直接說明結構體變量

struct 
{char *name;  //姓名int num;  //學號int age;  //年齡float score;  //成績
} student;

這種定義方式并不常用,這樣做書寫雖然簡單,但是因為沒有結構體名,后面就沒法用該結構體定義新的變量。
4.typedef重定義

typedef struct 
{char *name;  //姓名int num;  //學號int age;  //年齡float score;  //成績
} STU;
STU student;

這種方式比較常見,我們使用typedef重定義結構體為STU,這里STU就是此結構體類型,可以用STU去定義結構體變量

1.3 初始化

1.在定義結構體變量的時候全部初始化

struct stu
{char *name;  //姓名int num;  //學號int age;  //年齡float score;  //成績
}student={“ha”,1234,56,99};

2.定義完結構體變量后,之后只能單個賦值

struct stu
{char *name;  //姓名int num;  //學號int age;  //年齡float score;  //成績
};
struct stu  student;
student.name="ha";
student.num=1234;
student.age=56;
student.score=99;

1.4 調用

結構體變量.成員

結構體變量名+點(’.’)+成員就可以調用了

1.5 結構體指針

當一個指針變量指向結構體時,我們就稱它為結構體指針。C語言結構體指針的定義形式一般為:

struct 結構體名 *變量名;
//結構體
struct stu{char *name;  //姓名int num;  //學號int age;  //年齡float score;  //成績
} stu1 = { "hah", 12, 18, 23, 136.5 };
//結構體指針
struct stu *pstu = &stu1;

注意結構體變量名和數組名不同,數組名在表達式中會被轉換為數組指針,而結構體變量名不會,無論在任何表達式中它表示的都是整個集合本身,要想取得結構體變量的地址,必須在前面加&,所以給 pstu 賦值只能寫作:

1.6 獲取結構體成員

通過結構體指針可以獲取結構體成員,一般形式為:

(*pointer).memberName

或者:

pointer->memberName

第一種寫法中,.的優先級高于*,(pointer)兩邊的括號不能少。如果去掉括號寫作pointer.memberName,那么就等效于*(pointer.memberName),這樣意義就完全不對了。

第二種寫法中,->是一個新的運算符,習慣稱它為“箭頭”,有了它,可以通過結構體指針直接取得結構體成員;這也是->在C語言中的唯一用途。

1.7 結構體內存分析

注意點

  1. 給整個結構體變量分配儲存空間和數組一樣,從內存地址比較大的開始分配
  2. 給結構體變量中的屬性分配儲存空間也和數組一樣,從所占內存地址比較小的開始分配
  3. 定義結構體類型不會分配儲存空間,只有定義結構體變量的時候才會分配儲存空間
  • 結構體在分配內存的時候,會做一個內存對齊的操作
  • 會先獲取所有屬性中占用內存最大的屬性的字節數
  • 然后在開辟出最大屬性字節的內存給第一個屬性,如果分配給第一個屬性之后還能繼續分配給第二個屬性,那么就繼續分配給第二個屬性
  • 如果分配給第一個屬性之后,剩余的內存不夠分配給第二個屬性了,那么會再次開辟最大屬性的內存,再次分配 依次類推
#include <stdio.h>int main(){//定義結構體struct Person{char name; // 1 個節點  //開辟4個字節 char 占用1個int age;  // 4個字節   // 剩余三個 不夠int  再開辟4個字節int money; // 4個字節 // 再開辟4個字節};struct Person p; // 所以p = 4+4+4printf("sizeof(p) = %i\n",sizeof(p)); // 12個字節return 0;
}

(二)共用體(聯合體):union

2.1概念

  • 所有變量共用一段空間
  • 每次分配按最大長度進行分配
  • 是一種構造數據類型
  • 同一時刻只能保存一個成員的值
  • 不能直接引用共用體變量名

2.2定義

它的定義和結構體一樣,分為先定義共用體再說明共用體變量、在定義共用體的同時說明共用體變量、直接說明共用體變量

union 共用體名{成員列表
};

示例:

//先定義共用體再說明共用體變量
union data{int n;char ch;double f;
};
union data a, b, c;

2.3 引用

和結構體一樣,通過共用體變量名 . 成員名

union data{int n;char ch;double f;
} a, b, c;
a.n=3;

關于共用體的詳細介紹可以看下這篇文章C語言共用體(C語言union用法)詳解,講到共用體這里要說明一下大小端模式的問題。
大小端
小端模式:低地址存放低字節,高地址存放高字節
大端模式:低地址存放高字節,高地址存放低字節

(三)枚舉:enum

3.1 概念

  • 作用:列舉出所有的可能性,增強代碼的可閱讀性
  • 枚舉成員都是常量
  • 不能再對已經定義好的枚舉常量賦值

3.1 定義

enum 枚舉名 
{
枚舉變量
};

示例:

enum week
{ 
Mon, Tues, Wed, Thurs, Fri, Sat, Sun};
typedef enum
{
Mon, Tues, Wed, Thurs, Fri, Sat, Sun
}Date;

枚舉是一種類型,通過它可以定義枚舉變量:

Date a,b,c

我們也可以給每個名字都指定一個值:

enum week{ Mon = 1, Tues = 2, Wed = 3, Thurs = 4, Fri = 5, Sat = 6, Sun = 7 };

更為簡單的方法是只給第一個名字指定值:

enum week{ Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun };

這樣枚舉值就從 1 開始遞增,跟上面的寫法是等效的。
也可以在定義枚舉類型的同時定義變量:

enum week{ Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun } a, b, c;

有了枚舉變量,就可以把列表中的值賦給它:

enum week{ Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun };
enum week a = Mon, b = Wed, c = Sat;

或者:

enum week{ Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun } a = Mon, b = Wed, c = Sat;

特點:可以在定義枚舉時給成員賦值,被賦值的成員往后依次增加1,也可以在中間改變某一個成員的值。

3.1 引用

直接使用就行,需要注意的是**枚舉列表中的數據作用范圍是全局的,不能在定義與它們名字相同的白能量;Mon、Tues、Wed 等都是常量,不能對它們賦值,只能將它們的值賦給其他的變量。
示例:

#include <stdio.h>
int main(){enum week{ Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun } day;scanf("%d", &day);switch(day){case 1: puts("Monday"); break;case 2: puts("Tuesday"); break;case 3: puts("Wednesday"); break;case 4: puts("Thursday"); break;case 5: puts("Friday"); break;case 6: puts("Saturday"); break;case 7: puts("Sunday"); break;default: puts("Error!");}return 0;
}

Mon、Tues、Wed 這些名字都被替換成了對應的數字。這意味著,Mon、Tues、Wed 等都不是變量,它們不占用數據區(常量區、全局數據區、棧區和堆區)的內存,而是直接被編譯到命令里面,放到代碼區,所以不能用&取得它們的地址。這就是枚舉的本質。


本文章僅供學習交流用禁止用作商業用途,文中內容來水枂編輯,如需轉載請告知,謝謝合作

微信公眾號:zhjj0729

微博:文藝to青年

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/531448.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/531448.shtml
英文地址,請注明出處:http://en.pswp.cn/news/531448.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

插入排序之表插入排序

1.表插入排序只是求得一個有序的鏈表&#xff0c;它是修改指針的值來代替移動記錄&#xff0c;操作過程如下 2.但是這樣只能進行順序查找&#xff0c;不能進行隨機查找&#xff0c;為了能實現有序表的折半查找&#xff0c;需要對記錄進行重新排列。操作過程如下&#xff1a; 3.…

電容降壓LED驅動電路

電容降壓電路具有體積小、成本低、電流相對穩定等優點&#xff0c;可應用于小功率的LED驅動電路中&#xff0c;本文主要介紹了電容降壓電路的基本電路 圖一&#xff1a; 電容降壓式簡易電源的基本原理如圖一所示&#xff0c;C3為降壓電容器&#xff1b;D4為半波整流二極管&…

延時電路分析

延時電路經常會用到&#xff0c;RC電路是比較簡單的電路。在電路設計中經常會用到將電阻和電容正極連接&#xff0c;電阻另一端接上電源&#xff0c;電容負極接地。 簡單的延時電路 上面就是延時的電路圖了&#xff0c;延時的時間為T-ln((VCC-Vout)/VCC)RC&#xff0c;公式中的…

恒流電路的分析(一)

在這里分析一個簡單的LED恒流電路&#xff0c;軟件采用Multisim進行波形采集 一、元器件 R1為80KΩ左右的金屬膜電阻&#xff1b;Q選取耐壓值超過350V的VPN三極管&#xff1b;D選取2V左右的穩壓二極管(如1N4680)&#xff1b;C2選取10V、100UF以上的電解電容&#xff1b;R2選擇…

ST-LINK USB communication error解決方法

今天在用stlink-v2下載程序時出現ST-LINK USB communication error&#xff0c;突然就出現了這個問題&#xff0c;在網上找了好多解決辦法都不可以用&#xff0c;下面給出我的解決方案&#xff0c;文章末尾給出了網上的幾種解決辦法&#xff0c;僅供參考。 第一步&#xff1a;找…

ajax實現上傳文件

1.html部分 <input style"width: 280px" type"file" name"upLoadProjectPlan" id"upLoadProjectPlan" value"<%taskAppend.getTaskAllocationDoc()%>"/><a style"float: right; margin-right: 40px&qu…

利用STM32制作紅外測溫儀之硬件設計

最近受疫情的影響詳細大家都在家里沒事干&#xff0c;這里利用stm32最小系統做一個紅外測溫儀 這篇教程里我們來制作紅外測溫儀需要用到的硬件&#xff0c;關于PCB的工程文件&#xff0c;后文會給出。 &#xff08;一&#xff09;系統分析 由于我們的功能比較單一&#xff0c;…

如何在博客中插入背景音樂

1.首先進入網音樂官方網站&#xff1b; 2.查找自己喜歡的歌&#xff0c;看到如下界面 3.點擊"生成外鏈播放器" 4.看到下面的html代碼了嗎&#xff1f;將代碼進行復制。 5.進入博客園&#xff0c;點擊 "管理" ->"設置"&#xff0c; 將代碼復制…

常用存儲器介紹

注意&#xff1a;"易失/非易失"是指存儲器斷電后&#xff0c;它存儲的數據內容是否會丟失的特性。 &#xff08;一&#xff09;RAM和ROM 1.1 RAM RAM即隨機存儲器&#xff0c;它是指存儲器中的數據被讀入或者寫入與信息所在位置無關&#xff0c;時間都是相同的 1…

TortoiseGit與github實現項目的上傳

1. 下載并安裝相關軟件 這里主要涉及的軟件包括msysgit和TortoiseGit。 msysgit的下載地址&#xff1a;http://msysgit.googlecode.com/files/Git-1.7.4-preview20110204.exe TortoiseGit的下載地址&#xff1a;http://code.google.com/p/tortoisegit/downloads/list&#xff0…

Uboot啟動

&#xff08;一&#xff09;uboot 配置編譯分析 u-boot源碼是通過gcc和Makefile組織編譯的&#xff0c;頂層目錄下的Makefile可通過boards.cfg來設置開發板的定義 然后遞歸調用各級子目錄下的Makefile&#xff0c;把編譯過的程序連接成u-boot boards.cfg文件&#xff1a; 開發…

行列式計算的兩種方法

#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define N 100 using namespace std; int a[N][N]; double aa[N][N]; int n;/**********************************************************/ //求行列式的值&#xff1…

uboot啟動流程分析

Uboot的啟動流程分為兩個階段&#xff0c;第一階段主要是匯編語言編寫&#xff0c;第二階段是C語言編寫&#xff0c;每個階段所做的工作不同&#xff0c;這篇文章分析的是uboot 2010版&#xff0c;以tiny4412的uboot為例。 啟動過程涉及的主要文件&#xff1a; arch/arm/cpu/a…

(一)uboot的移植與制作

目錄&#xff08;一&#xff09;環境&#xff08;二&#xff09;流程分析&#xff08;三&#xff09;具體步驟在裸機啟動流程里涉及到BL1&#xff0c;BL2為系統的加載啟動項&#xff0c;全稱為BootLoader。 Boot Loader 是在操作系統內核運行之前運行的一段小程序。通過這段小程…

jquery ajax(實現單獨提交某個form)

function submitTaskScore(formid) {//formid表示的是表單的id$.ajax({type:"post",url:"companyAndDistributeAction!scoreTask",//后臺處理程序data:$(formid).serialize(),success:function(){document.getElementById("hjzggContent").inner…

(二)linux內核鏡像制作

&#xff08;一&#xff09;目的 在進行嵌入式開發的時候&#xff0c;我們往往會先在電腦上安裝交叉編譯器&#xff0c;然后編譯目標板上的代碼&#xff0c;最后把代碼下載到電路板中&#xff0c;嵌入式系統組成包括&#xff1a;BootLoaderkernelfilesystemapplication&#x…

js+css實現骰子的隨機轉動

網上找的例子&#xff0c;然后增添了新的東西&#xff0c;在這里展示一下...... 效果圖預覽&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html x…

linux安裝交叉編譯環境

&#xff08;一&#xff09;交叉編譯器的簡介 &#xff08;1&#xff09;本地編譯 在了解交叉編譯之前我們首先介紹一下另一個概念&#xff1a;本地編譯 之前所做的C開發屬于本地編譯&#xff0c;即在當前PC下&#xff08;x86的CPU下&#xff09;&#xff0c;直接編譯出可以運…

jsp實現郵件的發送

如果程序出現 454 Authentication failed, please open smtp flag first! 錯誤&#xff0c;那么一般是郵箱沒有開通POP3/SMTP服務&#xff0c;登錄郵箱&#xff0c;在設置中開啟該服務即可 &#xff01; 另外需要的jar包如下: imap.jar, mail.jar, smtp.jar, 可以自己在網上下…

linux的mount和umount指令使用

mount即掛在操作&#xff0c;磁盤或分區創建好文件系統后需要掛載到一個目錄&#xff08;一般mount在/mnt下&#xff09;才能使 用&#xff0c;和winsdows不同的是在linux下需要手動掛載。 用法&#xff1a;mount [-t文件系統] [選項] 設備目錄注意&#xff1a;[ ]為可選項…