C語言加強

来源:https://www.cnblogs.com/jll133688/p/18175474
-Advertisement-
Play Games

變數、指針和關鍵字 兩個口訣: 變數變數,能變,就是能讀能寫,必定在記憶體(RAM)里 指針指針,保存的是地址,32 位處理器中的地址都是 32 位的,無論是什麼類型的指針變數,都是 4 位元組 指針 對於 32 位處理器裡面,地址是 32 位的,所以指針的大小為 4 位元組,sizeof(p) = 4 ...


變數、指針和關鍵字

兩個口訣:

  • 變數變數,能變,就是能讀能寫,必定在記憶體(RAM)里
  • 指針指針,保存的是地址,32 位處理器中的地址都是 32 位的,無論是什麼類型的指針變數,都是 4 位元組

指針

  1. 對於 32 位處理器裡面,地址是 32 位的,所以指針的大小為 4 位元組,sizeof(p) = 4sizeof(*p) = 指針所指向的類型所占的空間

變數

  1. 只讀的常量一般放在 flash 中,所以只讀的變數加上 const 可以節省記憶體,但有時候為了優化也可能會放在記憶體里

extern 關鍵字

  1. 如果想在 a.c 中引用 b.c 中的全局變數 int b ,需要在 a.c 中加入:
    1. extern int b
    2. 包含頭文件 #include "b.h" ,然後在頭文件中寫 extern int b

註意 extern int b 不能被賦值!!!這個是聲明,表示 b 是什麼
不建議使用 extern,可以使用函數來進行值傳遞

static 關鍵字

  1. 對於全局變數,如果不加 static,全局變數的作用域為整個程式,加上 static 作用域就變為該文件了(函數前加 static 也是同樣的作用)
  2. 對於在函數內定義的變數,加上 static 的變數僅會初始化一次,再次調用該函數時,仍為上一次函數調用的結果,不會再次初始化

volatile 關鍵字

  • 不能自作主張優化變數,直接存取原始記憶體地址

  • 應用場景:

    • 中斷服務程式中修改的供其他程式檢測的變數,需要用 volitile
    • 多任務環境中個任務間共用的標誌加 volitile
    • 存儲器映射的硬體存儲器要加 volitile

    後面兩個場景還沒用到,等用到再具體補充

結構體

  • 結構體是不占記憶體的,是一種類型,用結構體定義了變數之後(實例化)才會分配記憶體空間

結構體對齊

為什麼會有記憶體對齊

  1. 平臺原因:不是所有的硬體平臺都能訪問任意記憶體地址上的任意數據,某些硬體平臺只能在某些地址處取某些特定類型的數據,否則拋出硬體異常。為了同一個程式可以在多平臺運行,需要記憶體對齊。
  2. 硬體原因:經過記憶體對齊後,CPU 訪問記憶體的速度大大提升

對齊規則

  1. 結構體每個成員相對結構體首地址的偏移量是對齊參數的整數倍,如有需要會在成員之間填充位元組。編譯器在為結構體成員開闢空間時,首先檢查預開闢空間的地址相對於結構體首地址的偏移量是否為對齊參數的整數倍,若是,則存放該成員,若不是,則填充若幹位元組,以達到整數倍的要求。

這裡的對齊參數取每個變數自身對齊參數和系統預設參數#pragma pack(n)(一般為 8)中較小的那個

  1. 結構體變數所占空間的大小是對齊參數大小的整數倍。如有需要會在最後一個成員末尾填充若幹位元組使得所占空間大小是對齊參數大小的整數倍。

這裡的對齊參數取結構體中所有變數對齊參數的最大值和系統預設參數對比取較小的

  • 即結構體變數所占的空間大小需要經過兩次對齊

圖解

| char |     |     |     | 4位元組
| int  | int | int | int | 4位元組
| short|short|     |     | 4位元組
| char |     |short|short| 4位元組
| int  | int | int | int | 4位元組

實例

  • 實例 1:
typedef struct
{
    char c;
    short d;
    static int a;
}A;
| char |     | 2位元組
| short|short| 2位元組

易錯點:對於結構體中的 static int a ,靜態數據成員存放位置與結構體實例的存儲地址無關,不算在裡面

只有 C++ 結構體中才有 static,C 語言中不允許有

  • 實例 2:
typedef struct 
{
    double b;
    int c;
}D;
    
typedef struct 
{
    bool a;   // bool為1位元組
    D d;
    double b;
    int c;
}E;
|bool|-----------------------------------| 8位元組
|--------------------D-------------------| 8位元組
|--------------------D-------------------| 8位元組
|------------------double----------------| 8位元組
|---------int--------|-------------------| 8位元組

易錯點:D 與預設的 8 比,8 小,取 8 為對齊參數

變數賦值

  • a = 123 等價於
p = &a;
*p = 123;  // 將a的值變為123
  • A.age = 20 等價於(A 為結構體)
pt = &A;
pt->age = 20;  // pt為指針,取成員用"->",結構體用"."
*pt = A2;     // 將A變成A2的值

結構體指針

typedef struct student{
    char *name;
    int age;
    struct student *classmate;   // 結構體中只能用指針,長度為4個位元組(鏈表)
}student, *pstudent;

student zhangsan = {"zhangshan", 10, NULL};
student lili = {"lili", 20, NULL};
zhangsan.classmate = &lili;  // 構成鏈表
name = zhangsan.classmate->name;   // zhangsan為結構體,用"."取值,classmate為指針,用"->"取值

函數指針

void (*add){};  // 函數指針,變數,占4位元組

typedef struct student{
    char *name;
    int age;
    void (*good_work)(void);  // 函數指針
    struct student *classmate;
}student, *pstudent;

// add為函數指針,也可以寫成&add
// 函數指針是變數,所以可以賦值為地址,函數不是變數,只能被調用
student ss[2] = {{"zhangshan", 10, add, NULL}, {"lili", 20, add, NULL}};  // 結構體數組

ss[1].good_work();   // 結構體調用函數指針,用"."
pstudent get(void){
    int type = 1;
    return &ss[type];  // 返回結構體指針
}  // 應儘量避免使用全局變數,可以將變數封裝在函數里
pstudent a;
a = get();
a->good_work();   //這裡a為結構體指針,用"->"

全局變數與局部變數

  • 全局變數:斷電時無,運行時有,初值來自 Flash

    • 有值時初始化:類似於 memcpy,把 Flash 數據段整體拷貝到記憶體
    • 初始值為 0/沒有初始化的:這些變數在記憶體里都放到了 ZI 段,類似於 memset,把 ZI 段全部清零
  • 局部變數:在棧里

參考資料

https://www.bilibili.com/video/BV1VM4y137Pm/?spm_id_from=333.999.0.0
https://blog.csdn.net/qq_41068271/article/details/83446623?spm=1001.2014.3001.5502


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • X-Frame-Options 是一個HTTP響應頭,用於控制網頁是否可以嵌套在 <frame>, <iframe>, <embed> 或者 <applet> 中。通過設置 X-Frame-Options 頭部,網站管理員可以防止網頁被嵌套到其他網站的框架中,從而有效防範點擊劫持等安全風險。下麵是關 ...
  • /******************************************************************************************************** * * file name: Zqh_順序表.c * author : keyword2 ...
  • 一、定義 在class的聲明裡頭,真正有用的兩樣東西是data members 和 member functions: Data members:表示根據這個class所產生的object裡頭會有些什麼東西,它事實上也是占據object記憶體的唯一東西(除非引入虛擬機制)。通常為數據的封裝性,我們把d ...
  • title: Django高級表單處理與驗證實戰 date: 2024/5/6 20:47:15 updated: 2024/5/6 20:47:15 categories: 後端開發 tags: Django表單 驗證邏輯 模板渲染 安全措施 表單測試 重定向管理 最佳實踐 引言: 在Web應用開 ...
  • NumPy 創建數組 NumPy 中的核心數據結構是 ndarray,它代表多維數組。NumPy 提供了多種方法來創建 ndarray 對象,包括: 使用 array() 函數 array() 函數是最常用的方法之一,它可以將 Python 列表、元組甚至其他數組轉換為 ndarray 對象。 語法 ...
  • 刪除A中與B相同的元素 目錄刪除A中與B相同的元素程式驗證輸出結果 程式 #include <stdio.h> /******************************************************************* * * file name: 刪除A中與B相同的元 ...
  • OutOfMemoryError是Java程式中常見的異常,通常出現在記憶體不足時,導致程式無法運行。藉助MAT記憶體分析工具分析可能的記憶體泄漏代碼問題定位。 ...
  • 具有查看日期時間、天氣、工作日、記錄喝水、查詢微博熱搜、60s讀世界和各種小工具的桌面工具,可以在托盤區單擊隱藏和彈出,或使用快捷鍵Alt+1 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...