C語言---自定義類型(上)(結構體類型)

結構體

????????結構體的定義與聲明

? ? ? ? ? ? ? ? 結構體其實和數組一樣,都是一些值的集合,只不過數組是一系類相同類型的值,而結構體里邊的成員可以是不同的數據類型。

? ? ? ? ? ? ? ? 關于它的聲明,所用到的關鍵字是struct。

? ? ? ? ? ?聲明的語法如下:

? ? ? ? ? ?struct 結構體名

? ? ? ? ? {

????????????????成員變量列表;

? ? ? ? ? ?}變量名;

????????????????我先舉個例子,就比如一個學生有名字、年齡、成績等信息。那么此時就可以用結構體來描述它。

struct Stu
{char name[20];//名字int age;double score;
};

????????結構體變量的定義和初始化及其訪問

????????????????定義

????????????????在剛才創建完成了結構體之后,我們就可以創建結構體的變量了。

? ? ? ? ? ? ? ? 一共有三種方式:下面以代碼加注釋的方式給出。

struct Stu
{char name[20];//名字int age;double score;
}stu1;//在定義結構體的時候就創建的全局變量struct Stu stu2;//創建的全局結構體變量int main()
{struct Stu stu3;//創建的局部結構體變量return 0;
}

????????????????初始化

? ? ? ? ? ? ?剛才上邊的代碼已經創建了幾個Stu類型的結構體變量,現在我給結構體變量stu3初始化,代碼如下

? ? ? ? ? ? ?//

? ? ? ? ? ? ?stu3 = {"xxc",18,99.0};//注意,我們給它初始化的時候需要按照順序,如果你想要按照自己的順序去初始化,那就要用到結構體成員訪問操作符?( . )

? ? ? ? ? ? ?stu3 = {.age = 20 , .name = "zhangsan" , .score = 98.5};

????????????????訪問結構體變量

????????????????訪問結構體的成員變量有兩種方式,第一種比較的直接,我們用結構體變量.成員名的方式去訪問結構體里的成員。第二種方式就要用到指針了,通過結構體指針->成員名的方式。代碼如下:

#include<stdio.h>struct Stu
{char name[20];int age;float score;
};int main()
{//第一種方式打印struct Stu stu = { "zhangsan",21,98.4f };printf("%d %f\n", stu.age, stu.score);//第二種方式打印,先得到結構體的地址,再用指針的方式去打印struct Stu* p = &stu;printf("%d %f\n", p->age, p->score);return 0;
}

????????嵌套結構體與匿名結構體類型

????????????????嵌套結構體:

? ? ? ? ? ? ? ? 嵌套結構體,顧名思義就是結構體充當了結構體的成員變量,請看下邊的代碼(同時,我會將訪問其成員變量也附加進去):

//注意:以下的代碼只是演示,沒有什么實際的含義
#include<stdio.h>
struct id
{char ID[25];int x;
};struct Stu
{char name[20];struct id identity;
};int main()
{struct Stu stu1 = { "zhangsan",{"123456",2} };return 0;
}

????????????????匿名結構體:

????????????????匿名結構體就是結構體在創建的時候沒給它名字,如下

struct
{
char name[20];
int age;
};

? ? ? ? ? ?這樣的話就不能創建結構體的變量了,只能用三種創建方法的第一種來創建,就是在定義的時候直接創建。并且你會發現當你取出他的地址賦值給一個匿名結構體類型的指針變量的時候是會失敗的。因為C標準認為它們是兩種不同的類型。所以往往匿名結構體類型只能用一次。

????????結構體的內存對齊

? ? ? ? ? ? ? ? 每一種數據只要存在在內存當中就肯定有大小,結構體也不例外,接下來所要討論的就是結構體的內存大小,C語言給出了一套計算它大小的規則,我們稱之為結構體的內存對齊。

? ? ? ? ? ?對齊規則:

????????????????1.結構體的第一個成員對齊到和結構體變量起始位置偏移量為0的地址處

? ? ? ? ? ? ? ? 2.其他成員變量要對齊到某個數字(對齊數)的整數倍的地址處

? ? ? ? ? ? ? ? 3.結構體的總大小為最大對齊數的整數倍

? ? ? ? ? ? ? ? 接下來我們先來解釋一下幾個名詞的含義:

????????????????偏移量:我們可以借助offsetof宏來幫助我們理解,offsetof可以計算出結構體的成員相較于結構體起始位置的偏移量。offsetof有兩個參數,第一個參數是結構體變量名字,第二個參數是結構體內部的成員名。??

? ? ? ? ? ? ? ? 由上圖我們可以知道每個結構體成員的偏移量是多少,如果你還沒有概念,請不要著急,我會把所有名詞解釋完之后再次回過頭來全部解釋一下。

? ? ? ? ? ? ? ? 對齊數: 在我們常見的編譯器vs里邊,默認的對齊數是8,但在計算結構體大小的時候,我們需要將默認的對齊數與該結構體成員變量的大小做比較,取較小的那個作為我們計算大小時候的依據。

? ? ? ? ? ? ? ? 最大對齊數:結構體里邊的每一個成員變量都有一個對齊數,它們之中最大的那個就叫做最大對齊數。

? ? ? ? ? ? ? ? 了解了以上的規則與概念之后,我們再將上邊截圖里邊的結構體拿出來,來根據規則計算一下它的大小。

????????????????結構體嵌套結構體的內存對齊

????????????????當我們想要計算的結構體里邊有結構體嵌套的時候,它的大小又該如何計算呢?

? ? ? ? ? ? ? ? 這時候,在上邊規則的三條規則之下還有一條規則。

? ? ? ? ? ?4.當存在嵌套結構體的時候,該結構體成員對齊到自己內部成員的最大對齊數的整數倍處,結構體的大小就是全部成員(包括嵌套結構體的成員)的最大對齊數的整數倍。

? ? ? ? ? ? ? ? 下邊來看一個例子:

????????????????修改默認對齊數:

? ? ? ? ? ? ? ? 我們在上邊已經提到過了,在vs里邊的默認對齊數為8,當我們覺得這個默認對齊數不合適的時候,我們就可以用預處理指令#pragma來修改默認的對齊數。

#include<stdio.h>
#pragma pack(1)//設置默認對齊數為1
struct test
{char c1;char c2;
};
#pragma pack()//取消設置的默認對齊數,還原為默認對齊數為8的狀態。
int main()
{struct test test2;printf("%d\n", sizeof(test2));return 0;
}

????????結構體傳參

????????????????函數的傳參分為兩種,一種是傳值,一種是傳址。下邊的代碼將結構體的兩種傳參方式一并演示。

#include<stdio.h>
struct s1
{char a;int b;char c;
};void test1(struct s1 s)
{printf("test1的打印:%d\n", s.b);
}void test2(struct s1* ps)
{printf("test2的打印:%d\n", ps->b);
}int main()
{struct s1 sss;sss.b = 10;test1(sss);test2(&sss);return 0;
}

? ? ? ? ? ? ? ? 這里再補充一個點,利用地址傳參可以很好的提升程序的運行效率,因為如果是傳值調用的話,程序會在內存里又開辟一塊空間來臨時拷貝實參。

????????結構體實現位段

? ? ? ? 首先明確位段在定義時候的兩個注意點

? ? ? ? 1.位段的成員必須是int,unsigned int,signed int,char,在C99中,位段成員的類型還可以是其他類型

? ? ? ? 2.? 位段的成員名后邊有一個冒號和一個數字。

? ? ? ? 如下就是一個基本的位段的定義

struct s
{int a : 2;int b : 4;int c : 6;
};

????????????????位段的內存分配:

? ? ? ? ? ? ? ? 在定義位段的時候,位段的每一個成員的冒號后邊的數字代表的是比特位的意思,也就是在定義位段的成員變量的時候,已經把它所占的空間大小也限定住了。

? ? ? ? ? ? ? ? 位段的空間是按照4個字節或者1個字節的大小來開辟空間的。還有一個值得注意的點就是位段不具有移植性,當需要跨平臺使用的不推薦使用位段。

? ? ? ? ? ? ? ? 接下來用一個例子來說明位段的內存分配:

? ? ? ? ? ? ? ? 由以上的例子可見,位段的作用本質上還是在節約內存空間的消耗。

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

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

相關文章

Java觀察者模式實現方式與測試方法

一、實現方式 自定義實現 通過手動定義Subject和Observer接口&#xff0c;實現一對多依賴關系&#xff1a; // 觀察者接口 public interface Observer {void update(float temp, float humidity, float pressure); } // 主題接口 public interface Subject {void registerObser…

leetGPU解題筆記(1)

1.題面 題目要求 向量加法 實現一個程序&#xff0c;在GPU上對兩個包含32位浮點數的向量執行逐元素加法。該程序應接受兩個長度相等的輸入向量&#xff0c;并生成一個包含它們和的輸出向量。 實現要求 禁止使用外部庫 solve函數簽名必須保持不變 最終結果必須存儲在向量C中 示例…

5. JVM 的方法區

1. JVM介紹和運行流程-CSDN博客 2. 什么是程序計數器-CSDN博客 3. java 堆和 JVM 內存結構-CSDN博客 4. 虛擬機棧-CSDN博客 5. JVM 的方法區-CSDN博客 6. JVM直接內存-CSDN博客 7. JVM類加載器與雙親委派模型-CSDN博客 8. JVM類裝載的執行過程-CSDN博客 9. JVM垃圾回收…

網絡安全的基本練習

一.docker搭建 1.安裝dockerapt-get install docker.io docker-compose2.編寫配置文件&#xff08;注意路徑正確&#xff09;vim /etc/systemd/system/docker.service.d/http-proxy.conf[Service] Environment"HTTP_PROXYhttp://科學上網訪問的ip:端口" Environment&…

380. O(1) 時間插入、刪除和獲取隨機元素

實現RandomizedSet 類&#xff1a; RandomizedSet() 初始化 RandomizedSet 對象 bool insert(int val) 當元素 val 不存在時&#xff0c;向集合中插入該項&#xff0c;并返回 true &#xff1b;否則&#xff0c;返回 false 。 bool remove(int val) 當元素 val 存在時&#xff…

【LeetCode Hot100 | 每日刷題】字母異位詞分組

題目鏈接&#xff1a;49. 字母異位詞分組 - 力扣&#xff08;LeetCode&#xff09; 題目&#xff1a; 給你一個字符串數組&#xff0c;請你將 字母異位詞 組合在一起。可以按任意順序返回結果列表。 示例 1: 輸入: strs ["eat", "tea", "tan"…

docker 安裝windows

目錄 下載地址&#xff1a; 使用教程&#xff1a; docker compose 查看版本 測試啟動 hello-world 報錯1 The system cannot find the file specified&#xff1a; 檢查 Docker Desktop 是否運行中 報錯2HF_ENDPOINT 1. 臨時解決方案&#xff08;當前終端會話有效&…

docker compose 和build

目錄 docker compose 和build 的區別是什么&#xff1f; 核心差別&#xff1a; 1. docker build --platform linux/amd64 -f Dockerfile -t infiniflow/ragflow:nightly_lbg . 2. docker compose -f docker-compose-gpu.yml up -d 二者如何配合&#xff1f; 總結 docker …

裂變時刻:全球關稅重構下的券商交易系統躍遷路線圖(2025-2027)

——基于RWA清算、量子加密與實時非線性風控的下一代跨境基礎設施核心事件錨定&#xff1a;特朗普于7月7日對14國啟動分級關稅制裁&#xff08;日韓25%、東南亞30%-40%、金磚關聯國10%附加稅&#xff09;&#xff0c;引發日元兌美元暴跌至144.47、銅價單日跳漲3.2%、散戶單日交…

python爬蟲初入門——基本庫和寫入方法

1.準備環境 python環境&#xff1a;3.10 2.常用庫 1.請求庫&#xff1a;實現 HTTP 請求操作 requests&#xff1a;基于 urllib 編寫的&#xff0c;阻塞式 HTTP 請求庫&#xff0c;發出一個請求&#xff0c;一直等待服務器響應后&#xff0c;程序才能進行下一步處理。seleni…

Sonar掃描C#代碼配置

需要的工具 MSBuild、sonar-scanner-4.6.1.2450-windows、jdk1.8.0_181 下載地址&#xff1a;https://download.csdn.net/download/code12313/91315686 配置sonar的地址 一、環境變量配置 1.新建變量&#xff0c;nameSONAR_RUNNER_MSBUILD_HOME。valueD:\work\dev\dev_serve…

python 在運行時沒有加載修改后的版本

陳舊的Python字節碼 (.pyc 文件)&#xff1a;最常見的原因&#xff01;Python 會把你修改的 .py 文件編譯成 .pyc 字節碼來加速后續運行。有時&#xff0c;即使你修改了 .py 文件&#xff0c;系統可能仍然固執地加載舊的、未被刪除的 .pyc 文件。1. 用“硬編碼探針”強制驗證# …

【會員專享數據】2013-2024年我國省市縣三級逐年SO?數值數據(Shp/Excel格式)

之前我們分享過2013-2024年全國范圍逐年SO?柵格數據&#xff08;可查看之前的文章獲悉詳情&#xff09;&#xff01;該數據來源于韋晶博士、李占清教授團隊發布在國家青藏高原科學數據中心網站上的中國高分辨率高質量近地表空氣污染物數據集。很多小伙伴拿到數據后反饋柵格數據…

出現SSL連接錯誤的原因和解決方案

介紹 SSL連接錯誤是一種常見但關鍵的問題&#xff0c;這可能會阻止客戶端和服務器之間的安全連接。這些錯誤發生在TLS握手過程失敗時&#xff0c;這意味著客戶端和服務器無法建立安全的HTTPS連接。這種失敗可以在SSL/TLS協商過程中的任何階段發生&#xff0c;從初始協議協議到…

vue3 el-date-picker 保存后 日期減一問題

在使用 el-date-picker&#xff08;Element UI 的日期選擇器組件&#xff09;時&#xff0c;如果你發現日期在保存到后臺后自動減一&#xff0c;這通常是由于時區差異或者是時間格式解析問題導致的。這里有一些可能的解決方案&#xff1a;1. 檢查前端發送的日期格式確保你在前端…

什么是IP關聯?跨境賣家如何有效避免IP關聯?

一位深圳賣家曾管理30個亞馬遜店鋪賬號&#xff0c;某日清晨發現所有賬號被批量封禁——原因竟是平臺檢測到這些賬號長期共享同一IP地址&#xff0c;判定為“IP關聯”。而在跨境領域如亞馬遜、eBay、Shopee、TikTok等平臺&#xff09;&#xff0c;對于IP關聯的判定都是比較嚴格…

Redis集群方案——哨兵機制

Redis Sentinel&#xff08;哨兵&#xff09;是Redis官方提供的高可用性(HA)解決方案&#xff0c;用于管理Redis主從架構并實現自動故障轉移。一、集群結構和作用哨兵是一個分布式系統&#xff0c;由多個哨兵節點組成&#xff1a;哨兵的作用如下&#xff1a;監控&#xff1a;Se…

1.2.3_2 TCP/IP模型

在這個視頻中&#xff0c;我們要探討TCP/IP模型。對于TCP/IP模型考試的要求是這樣的&#xff0c;首先我們需要記住它各個層次的名稱和順序&#xff0c;以及我們需要了解TCP/IP 模型和OSI參考模型&#xff0c;它們在設計理念上有哪些區別&#xff0c;設計理念的區別又導致了TCP/…

EVOLVEpro安裝使用教程-蛋白質語言模型驅動的快速定向進化

寫在前面&#xff1a;蛋白質是生命活動的基石&#xff0c;其功能和序列之間的復雜關系長期以來吸引著科學家們的關注。盡管深度突變掃描等實驗方法可以解析蛋白質突變的功能影響&#xff0c;但這些技術的應用范圍局限于序列空間的一小部分。近年來&#xff0c;基于蛋白質語言模…

【Linux】Rocky Linux 清華鏡像源安裝 GitLab

使用清華鏡像源安裝 GitLab 地址&#xff1a;清華鏡像源 1. 搜索 gitlab&#xff0c;我們選擇 gitlab-ce 社區版進行安裝 2. 新建 /etc/yum.repos.d/gitlab-ce.repo&#xff0c;內容為 注意&#xff1a;el$releasever 是清華鏡像源內的文件夾版本 [gitlab-ce] nameGitlab C…