C語言學習筆記-9

九、結構體

構造類型

不是基本類型的數據結構也不是指針類型, 它是若干個相同或不同類型的數據構成的集合

結構體類型

結構體是一種構造類型的數據結構,是一種或多種基本類型或構造類型的數據的集合。

1.結構體類型定義

定義:

(1).先定義結構體類型, 再去定義結構體變量

struct 結構體類型名{
成員列表;
};

struct stu{
int num;
char name[20];
char sex;
};
//有了結構體類型后, 就可以用類型定義變量了
struct stu lucy,bob,lilei;//定義了三個 struct stu 類型的變量,每個變量都有三個成員, 分別是 num name sex

(2).在定義結構體類型的時候順便定義結構體變量, 以后還可以定義結構體變量

struct 結構體類型名{
成員列表;
}結構體變量 1,變量 2;

struct 結構體類型名 變量 3, 變量 4;

struct stu{
int num;
char name[20];
char sex;
}lucy,bob,lilei;
struct stu xiaohong,xiaoming;
無結構體類型名

在定義結構體類型的時候, 沒有結構體類型名, 順便定義結構體變量,

因為沒有類型名, 所以以后不能再定義相關類型的數據了

struct {
成員列表;
}變量 1, 變量 2;

struct {
int num;
char name[20];
char sex;
}lucy,bob;
//以后沒法再定義這個結構體類型的數據了, 因為沒有類型名
最常用:

通常咱們將一個結構體類型重新起個類型名, 用新的類型名替代原先的類型

typedef struct stu{
int num;
char name[20];
char sex;
}STU;
//以后 STU 就相當于 struct stu
STU lucy;struct stu lucy;是等價的。

2.結構體變量的定義初始化及使用

1、 結構體變量的定義和初始化

(1):在定義結構體變量之前首先得有結構體類型, 然后再定義變量
(2):在定義結構體變量的時候, 可以順便給結構體變量賦初值, 被稱為結構體的初始化
(3):結構體變量初始化的時候, 各個成員順序初始化

struct stu{
int num;
char name[20];
char sex;
};struct stu boy;
struct stu lucy={
101,
"lucy",
'f'
};
//結構體內后面的變量可以不初始化,中間的變量必須初始化

2、 結構體變量的使用

(1).結構體變量成員的引用方法 :結構體變量.成員名

struct stu{
int num;
char name[20];
char sex;
char* addr;
};
struct stu bob;
bob.num=101;//bob 是個結構體變量,但是 bob.num 是個 int 類型的變量
bob.name 是個字符數組,是個字符數組的名字,代表字符數組的地址,是個常量
//bob.name ="bob";是不可行,是個常量
strcpy(bob.name,"bob");strcpy(bob.addr,"beijing")//錯誤,bob.addr是個野指針
bob.addr="beijing";//正確
#include <stdio.h>
struct stu{
int num;
char name[20];
int score;
char *addr;
};
int main(int argc, char *argv[])
{
struct stu bob;
printf("%d\n",sizeof(bob));
printf("%d\n",sizeof(bob.name));
printf("%d\n",sizeof(bob.addr));
return 0;
}
//結構體大小,為各元素的大小之和

3、相同類型的結構體變量相互賦值

#include <stdio.h>
struct stu{
int num;
char name[20];
char sex;
};int main(int argc, char *argv[])
{
struct stu bob={101,"bob",'m'};
struct stu lilei;
lilei=bob;//類型相同
printf("%d %s %c\n",lilei.num,lilei.name,lilei.sex);
return 0;
}

3.結構體數組

結構體數組是個數組, 由若干個相同類型的結構體變量構成的集合

1、結構體數組的定義方法

struct 結構體類型名 數組名[元素個數];

struct stu{
int num;
char name[20];
char sex;
};
struct stu edu[3];//定義了一個 struct stu 類型的結構體數組 edu,
這個數組有3個元素分別是 edu[0]、 edu[1]、edu[2]

結構體數組元素的引用: 數組名[下標]

數組元素的使用

edu[0].num =101;//用 101 給 edu 數組的第 0 個結構體變量的 num 賦值
strcpy(edu[1].name,"lucy");
#include <stdio.h>
typedef struct student
{
int num;
char name[20];
float score;
}STU;
STU edu[3]={
{101,"Lucy",78},
{102,"Bob",59.5},
{103,"Tom",85}
};
int main()
{
int i;
float sum=0;
for(i=0;i<3;i++)
{sum+=edu[i].score;} 
printf("平均成績為%f\n",sum/3);
return 0;
}

4.結構體指針

即結構體的地址, 結構體變量存放內存中, 也有起始地址。咱們定義一個變量來存放這個地址, 那這個變量就是結構體指針變量。
結構體指針變量也是個指針, 既然是指針在 32 位環境下, 指針變量的占 4 個字節, 存放一個地址編號。

1、 結構體指針變量的定義方法:

struct 結構體類型名 * 結構體指針變量名;

struct stu{
int num;
char name[20];
};
struct stu * p;//定義了一個 struct stu *類型的指針變量
//變量名是p,p占4個字節,用來保存結構體變量的地址編號
struct stu boy;
p=&boy;boy.num=101;//可以,通過 結構體變量名.成員名
(*p).num=101;//可以,*p 相當于 p 指向的變量 boy
p->num=101;//可以,指針->成員名
//通過結構體指針來引用指針指向的結構體的成員, 前提是指針必須先指向一個結構體變量。

2、應用場景

(1): 保存結構體變量的地址

typedef struct stu{
int num;
char name[20];
float score;
}STU;int main()
{
STU *p,lucy;
p=&lucy;
p->num=101;
strcpy(p->name,"baby");
//p->name="baby";//錯誤,因為 p->name 相當于 lucy.name 是個字符數組的名字,是個常量
}

(2): 函數傳結構體變量的地址

#include<stdio.h>
#include<string.h>
typedef struct stu{
int num;
char name[20];
float score;
}STU;
void fun(STU *p)
{
p->num=101;
(*p).score=87.6;
strcpy(p->name,"lucy");
} int main()
{
STU girl;
fun(&girl);
printf("%d %s %f\n",girl.num,girl.name,girl.score);
return 0;
}

(3): 傳結構體數組的地址

結構體數組, 是由若干個相同類型的結構體變量構成的集合。 存放在內存里,
也有起始地址, 其實就是第 0 個結構體變量的地址。

#include<stdio.h>
#include<string.h>
typedef struct stu{
int num;
char name[20];
float score;
}STU;
void fun(STU *p)
{
p[1].num=101;
(*(p+1)).score=88.6;
}
int main()
{
STU edu[3];
fun(edu);
printf("%d %f\n",edu[1].num,edu[1].score);
return 0;
}
注意:

(1): 結構體變量的地址編號和結構體第一個成員的地址編號相同, 但指針的類型不同

#include <stdio.h>
typedef struct stu{
int num;
char name[20];
int score;
}STU;
int main(int argc, char *argv[])
{
STU bob;
printf("%p\n",&bob);//STU*
printf("%p\n",&(bob.num));//int*
return 0;
}

(2): 結構體數組的地址就是結構體數組中第 0 個元素的地址

#include <stdio.h>
struct stu{
int num;
char name[20];
int score;
};int main(int argc, char *argv[])
{
struct stu edu[3];
printf("%p\n",edu);//struct stu *
printf("%p\n",&(edu[0]));//struct stu *
printf("%p\n",&(edu[0].num));//int *
return 0;
}//各地址相同

5.結構體內存分配

規則 1: 以多少個字節為單位開辟內存

(1): 成員中只有 char 型數據 , 以 1 字節為單位開辟內存。
(2): 成員中出現了 short int 類型數據, 沒有更大字節數的基本類型數據。以 2 字節為單位開辟內存
(3): 出現了 int ,float 沒有更大字節的基本類型數據的時候以 4 字節為單位開辟內存。
(4): 出現了 double 類型的數據
情況 1:
在 vc6.0 和 Visual Studio 中里, 以 8 字節為單位開辟內存。
情況 2:
在 Linux 環境 gcc 里, 以 4 字節為單位開辟內存。
無論是那種環境, double 型變量, 占 8 字節。

(5):如果出現指針的話, 沒有占字節數更大的類型的, 以 4 字節為單位開辟內存。

struct stu{
char sex;
int age;
}lucy;
//lucy 的大小是 4 的倍數。

規則 2: 字節對齊

(1): char 1 字節對齊 , 即存放 char 型的變量, 內存單元的編號是 1 的倍數即可。
(2): short int 2 字節對齊 , 即存放 short int 型的變量, 起始內存單元的編號是 2 的倍數即可。

(3): int 4 字節對齊 , 即存放 int 型的變量, 起始內存單元的編號是 4 的倍數即可
(4): long int 在 32 位平臺下,4 字節對齊,即存放 long int 型的變量, 起始內存單元的編號是 4
的倍數即可
(5): float 4 字節對齊 , 即存放 float 型的變量, 起始內存單元的編號是 4 的倍數即可
(6): double
vc6.0 和 Visual Studio 環境下
8 字節對齊, 即存放 double 型變量的起始地址, 必須是 8 的倍數, double 變量占 8 字節

gcc 環境下
4 字節對齊, 即存放 double 型變量的起始地址, 必須是 4 的倍數, double 變量占 8 字節。

注意 3: 當結構體成員中出現數組的時候, 可以看成多個變量。
注意 4: 開辟內存的時候, 從上向下依次按成員在結構體中的位置順序開辟空間

#include<stdio.h>
struct stu{
char a;
short int b;
int c;
}temp;
int main()
{
printf("%d\n",sizeof(temp));
printf("%p\n",&(temp.a));
printf("%p\n",&(temp.b));
printf("%p\n",&(temp.c));
return 0;
}

在這里插入圖片描述

結果分析:
a 的地址和 b 的地址差 2 個字節
b 的地址和 c 的地址差 2 個字節

#include<stdio.h>
struct stu{
char a;
int c;
short int b;
}temp;
int main()
{
printf("%d\n",sizeof(temp));
printf("%p\n",&(temp.a));
printf("%p\n",&(temp.b));
printf("%p\n",&(temp.c));
return 0;
}

在這里插入圖片描述

結果分析:
a 和 c 的地址差 4 個字節
c 和 b 的地址差 4 個字節

struct stu{
char buf[10];
int a;
}temp;
//temp 占 16 個字節

在這里插入圖片描述

在 vc 和 Visual Studio 中占 16 個字節 a 和 b 的地址差 8 個字節
在 gcc 中占 12 個字節 a 和 b 的地址差 4 個字節
#include<stdio.h>
struct stu{
char a;
double b;
}temp;
int main()
{
printf("%d\n",sizeof(temp));
printf("%p\n",&(temp.a));
printf("%p\n",&(temp.b));
return 0;
}

在這里插入圖片描述

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

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

相關文章

Test——BUG篇

目錄 一軟件測試的生命周期 二BUG 1概念 2描述Bug 3Bug級別 4Bug的生命周期 三與開發人員發生爭執怎么辦 ?編輯1先自省&#xff1a;是否Bug描述不清晰 2站在用戶角度考慮并拋出問題 3Bug定級有理有據 4不僅要提出問題&#xff0c;還要給出解決方案 5Bug評審 5.1…

【Block總結】HWAB,半小波注意力塊|即插即用

論文信息 標題: HALF WAVELET ATTENTION ON M-NET+ FOR LOW-LIGHT IMAGE ENHANCEMENT 地址: arXiv:2203.01296 日期: 2022年3月 創新點 改進的分層架構 M-Net+: 提出了一個專為低光圖像增強設計的改良分層模型 M-Net+。該架構旨在緩解采樣過程中的空間信息損失問題。通過采用…

Spring 中的事務

&#x1f9fe; 一、什么是事務&#xff1f; &#x1f9e0; 通俗理解&#xff1a; 事務 一組操作&#xff0c;要么全部成功&#xff0c;要么全部失敗&#xff0c;不能只做一半。 比如你轉賬&#xff1a; A 賬戶扣錢B 賬戶加錢 如果 A 扣了錢但 B 沒收到&#xff0c;那就出問…

Flutter極速接入IM聊天功能并支持鴻蒙

Flutter極速接入IM聊天功能并支持鴻蒙 如果你們也是Flutter項目&#xff0c;想快速接入聊天&#xff0c;包括聊天的UI界面&#xff0c;強烈推薦這一家。因為我們已經完成了集成&#xff0c;使用非常穩定&#xff0c;集成也非常快捷方便。 而且&#xff0c;就在今天&#xff0c…

C# 類庫生成后自動復制到指定目錄

C# 類庫生成后自動復制到指定目錄 在C#中,當你開發了一個類庫項目(通常是.NET Core或.NET Framework項目),你可能會希望在構建(Build)完成后自動將生成的DLL文件復制到指定的目錄。有幾種方法可以實現這個需求,下面是一些常用的方法: 方法1:使用MSBuild的AfterBuild…

13-產品經理-產品多分支平臺管理

禪道16.0版本開始&#xff0c;優化和增強了產品的分支/平臺功能&#xff0c;主要特點如下&#xff1a; 多分支/平臺功能兼容各種大小型項目&#xff0c;項目/迭代可以關聯對應產品的某個分支/平臺。分支/平臺支持靈活管理&#xff0c;可以把分支/平臺理解為時間層面的概念&…

手搓多模態-04 歸一化介紹

在機器學習中&#xff0c;歸一化是一個非常重要的工具&#xff0c;它能幫助我們加速訓練的速度。在我們前面的SiglipVisionTransformer 中&#xff0c;也有用到歸一化層&#xff0c;如下代碼所示&#xff1a; class SiglipVisionTransformer(nn.Module): ##視覺模型的第二層&am…

Qt 入門 1 之第一個程序 Hello World

Qt 入門1之第一個程序 Hello World 直接上操作步驟從頭開始認識&#xff0c;打開Qt Creator&#xff0c;創建一個新項目&#xff0c;并依次執行以下操作 在Qt Creator中&#xff0c;一個Kits 表示一個完整的構建環境&#xff0c;包括編譯器、Qt版本、調試器等。在上圖中可以直…

深入理解MySQL:核心特性、優化與實踐指南

MySQL是一個開源的關系型數據庫管理系統(RDBMS)&#xff0c;由瑞典MySQL AB公司開發&#xff0c;目前屬于Oracle公司。它是目前世界上最流行的開源數據庫之一&#xff0c;廣泛應用于各種規模的Web應用和企業系統中。 目錄 一、核心特點 關系型數據庫&#xff1a; 開源免費&am…

Linux 系統安裝與優化全攻略:打造高效開發環境

一、開篇引言 &#xff08;一&#xff09;Linux 系統的廣泛應用 Linux 憑借其開源、穩定且安全的特性&#xff0c;在服務器、嵌入式設備以及開發環境等領域都有著極為廣泛的應用。 &#xff08;二&#xff09;撰寫本文的目的 為讀者提供一套全面且實用的指南&#xff0c;助…

代碼訓練day22回溯算法p1

1.組合 &#xff08;1&#xff09;模板 void backtracking(參數) {if (終止條件) {存放結果;return;}for (選擇&#xff1a;本層集合中元素&#xff08;樹中節點孩子的數量就是集合的大小&#xff09;) {處理節點;backtracking(路徑&#xff0c;選擇列表); // 遞歸回溯&#…

2024華為OD機試真題-任務最優調度(C++/Java/Python)-E卷-200分

2024華為OD機試最新E卷題庫-(D卷+E卷)-(JAVA、Python、C++) 目錄 題目描述 輸入描述 輸出描述 用例1 考點 題目解析 代碼 c++ java python 題目描述 給定一個正整數數組表示待系統執行的任務列表,數組的每一個元素代表一個任務,元素的值表示該任務的類型。請計算執…

每日習題:20250407

2025 2025 2025年 04 04 04月 06 06 06日 題目 1 設 X X X是實隨機變量&#xff0c;任意光滑的函數 f : R → R f:\mathbf{R} \rightarrow \mathbf{R} f:R→R&#xff0c;都有&#xff1a; E ( X f ( X ) ) E ( f ′ ( X ) ) E\left(Xf(X)\right)E\left(f(X)\right) E(Xf(X)…

TensorRT 有什么特殊之處

一、TensorRT的定義與核心功能 TensorRT是NVIDIA推出的高性能深度學習推理優化器和運行時庫&#xff0c;專注于將訓練好的模型在GPU上實現低延遲、高吞吐量的部署。其主要功能包括&#xff1a; 模型優化&#xff1a;通過算子融合&#xff08;合并網絡層&#xff09;、消除冗余…

JCR一區文章,壯麗細尾鷯鶯算法Superb Fairy-wren Optimization-附Matlab免費代碼

本文提出了一種新穎的基于群體智能的元啟發式優化算法——壯麗細尾鷯優化算法&#xff08;SFOA&#xff09;,SFOA從精湛的神仙鶯的生活習性中汲取靈感。融合了精湛的神仙鶯群體中幼鳥的發育、繁殖后鳥類喂養幼鳥的行為以及它們躲避捕食者的策略。通過模擬幼鳥生長、繁殖和攝食階…

使用Ubuntu18恢復群暉nas硬盤數據外接usb

使用Ubuntu18恢復群暉nas硬盤數據外接usb 1. 接入硬盤2.使用Ubuntu183.查看nas硬盤信息3. 掛載nas3.1 掛載損壞nas硬盤(USB)3.2 掛載當前運行的nas 4. 拷貝數據分批傳輸 5. 新舊數據對比 Synology NAS 出現故障&#xff0c;DS DiskStation損壞&#xff0c;則可以使用計算機和 U…

linux 安裝 mysql記錄

sudo apt-get install mysql-server 一直報錯&#xff0c;按照下面的終于安裝出來了 這個鏈接 https://cn.linux-console.net/?p13784 第 1 步&#xff1a;要刪除 MySQL 及其所有依賴項&#xff0c;請執行以下命令&#xff1a; sudo apt-get remove --purge mysql* 第 2 步…

UE5學習筆記 FPS游戲制作35 使用.csv配置文件

文章目錄 導入.csv要求首先創建一個結構體導入配置文件讀取配置 導入 .csv要求 第一行必須包含標題 第一列的內容必須不能重復&#xff0c;因為第一列會被當成行的名字&#xff0c;在數據處理中發揮類似于字典的key的作用 當前的配置文件內容如下 首先創建一個結構體 結構…

談談策略模式,策略模式的適用場景是什么?

一、什么是策略模式&#xff1f;?? 策略模式&#xff08;Strategy Pattern&#xff09;屬于??行為型設計模式??。核心思路是將一組??可替換的算法??封裝在獨立的類中&#xff0c;使它們可以在運行時動態切換&#xff0c;同時使客戶端代碼與具體算法解耦。它包含三個…

AGI大模型(10):prompt逆向-巧借prompt

1 提示詞逆向 明確逆向提示詞?程概念 我們可以給ChatGPT提供?個簡潔的提示詞,讓它能夠更準確地理解我們所討論的“逆向提示詞?程”是什么意思,并通過這個思考過程,幫它將相關知識集中起來,進?構建?個專業的知識領域 提示詞:請你舉?個簡單的例?,解釋?下逆向pro…