嵌入式:指針的指針、鏈表、UCOS 的 OSMemCreate 。

来源:http://www.cnblogs.com/leonlincq/archive/2017/01/16/6291474.html
-Advertisement-
Play Games

初看,UCOS 的 OSMemCreate 代碼,感覺有點怪怪的,比如,把 指針指向的地址 強制轉換成 指針的指針的指向地址 ?那轉換後 指針的指針 又是什麼? ... (1)、p_link = (void **)p_addr; //把 p_addr 的值(即地址)賦給 p_link ,但是,類型不 ...


初看,UCOS 的 OSMemCreate 代碼,感覺有點怪怪的,比如,把 指針指向的地址 強制轉換成 指針的指針的指向地址 ?那轉換後 指針的指針 又是什麼?

 

void  OSMemCreate (OS_MEM       *p_mem,
                   CPU_CHAR     *p_name,
                   void         *p_addr,
                   OS_MEM_QTY    n_blks,
                   OS_MEM_SIZE   blk_size,
                   OS_ERR       *p_err)
{
#if OS_CFG_ARG_CHK_EN > 0u
    CPU_DATA       align_msk;
#endif
    OS_MEM_QTY     i;
    OS_MEM_QTY     loops;
    CPU_INT08U    *p_blk;
    void         **p_link;

...

    p_link = (void **)p_addr;                               /* Create linked list of free memory blocks               */
    p_blk  = (CPU_INT08U *)p_addr;
    loops  = n_blks - 1u;
    for (i = 0u; i < loops; i++) {
        p_blk +=  blk_size;
       *p_link = (void  *)p_blk;                            /* Save pointer to NEXT block in CURRENT block            */
        p_link = (void **)(void *)p_blk;                    /* Position     to NEXT block                             */
    }
   *p_link             = (void *)0;                         /* Last memory block points to NULL                       */

 

(1)、p_link = (void **)p_addr;       //把 p_addr 的值(即地址)賦給 p_link ,但是,類型不一樣,所以 強制轉換 。

(2)、p_blk  = (CPU_INT08U *)p_addr;  //強制轉換,因為 p_addr 為 void* 形參 ,任意類型的指針。

(3)、loops  = n_blks - 1u;         //迴圈次數

(4)、for (i = 0u; i < loops; i++) {     //迴圈

(5)、 p_blk +=  blk_size;          //把地址增加 一個塊空間 大小

(6)、*p_link = (void  *)p_blk;      //把自增後的地址,賦值給 *p_link ,即寫入到 *(p_addr + blk_size )數組裡,因為,在(1)把p_addr 地址給了p_link。

(7)、p_link = (void **)(void *)p_blk;   //p_blk,是CPU_INT08U * 類型指針,所以,先強制轉換成(void *)任意類型的,然後,再用(void **)強制轉換,同1;

(8)、}                  //迴圈結束
(9)、*p_link = (void *)0;         //在鏈表結尾賦NULL。

 

在這裡,**p_link 無意義,因為 *p_link  相當於*(p_addr + loops * blk_size ),即 數組的值, 那**p_link (*值)是什麼?如果這個值,剛好是32位且申請過的空間,如 0x12345678,那麼**p_link,也許就有意義了?

 

還有,既然**p_link ,都沒用到過,那是否用 一級指針 就行了?沒必要用 二級指針?

於是用 Xcode 做了些測試,如下:

1、傳統教科書式用法,c -> b ->a

 

2、模仿UCOS的方法,b[0]=(a的地址),b[1]=(a的地址+3)。

2-1、發現有問題,調了下發現,任意類型的指針void *,自增,只增加1?

 

2-2、試了下地址,增加一個指針大小,就可以了。在這裡,sizeof(void *)  = sizeof(long int *) = 8 。用MAC的Xcode測試的。

 

3、同樣模仿UCOS的寫法,區別於2,指針類型都用 long int * ,不用 void * 。

3-1、和2相反,用指針自增是對的。

 

3-2、和2相反,加一個指針大小是錯的。

 

4、後來,想,既然UCOS,用了指針的指針,但都沒用到**p_link,只用到一級指針,那我是否可以把p_link都參數都加上*,變成使用**p_link,和*p_link?

結果一開始就錯了。編譯沒問題,語法沒錯誤,但是,p_p_b沒有指向任何地址,不能對*p_p_b賦值。

 

5、對4的修改,與UCOS寫法一樣用了指針的指針,**p_p_b 相當於**p_link。用**p_p_b來修改外面的數組,用p_p_b來指向不斷自增的外面數組的地址,且不需要重覆 p_p_b = &p_b(UCOS寫法需要,見(7),因為,UCOS,相當於用一級指針,地址改變,需要重覆賦地址,而,這裡二級指針指向了一個一級指針,一級變,二級會跟蹤)。

 

6、再細想,既然UCOS只用到一級指針的效果。那麼我是否可以直接用1級指針。(這裡有錯,本來的效果應該是p_b_1++,類似UCOS的寫法,需要 for 不斷的p_b_2 = p_b_1)

 

至此,結束。


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

-Advertisement-
Play Games
更多相關文章
  • 數據持久化是還原的前提,沒有數據的持久化,就無法還原記憶體優化表的數據,SQL Server In-Memory OLTP的記憶體數據能夠持久化存儲,這意味著記憶體數據能夠在SQL Server實例重啟之後自動還原。在創建持久化的記憶體優化表時,必須設置選項:memory_optimized=on,dura ...
  • getdate():當前系統日期與時間 DATEADD(DAY,5,GETDATE()):當前日期的基礎上加上x天 DATEDIFF(DAY,'2017-01-02','2017-01-13'):返回指定的兩個日期與時間的邊界數 DATEPART(MONTH,GETDATE()):返回當前指定日期的 ...
  • 經過一段時間的學習,完成了新聞發佈的基礎功能,進行一點小總結,方便日後回顧。下麵是我的一點小總結,不足之處請勿見笑。。。 ...
  • 《.Net程式員學用Oracle系列:導航目錄》 本文大綱 1、 " 字元函數 " 1.1、 "字元函數簡介" 1.2、 "語法說明及案例" 2、 " 數字函數 " 2.1、 "數字函數簡介" 2.2、 "語法說明及案例" 3、 " 日期函數 " 3.1、 "日期函數簡介" 3.2、 "語法說明及案 ...
  • on、where、having的區別 on、where、having這三個都可以加條件的子句中,on是最先執行,where次之,having最後。有時候如果這先後順序不影響中間結果的話,那最終結果是相同的。但因為on是先把不符合條件的記錄過濾後才進行統計,它就可以減少中間運算要處理的數據,按理說應該 ...
  • ①System.Data → DataTable,DataSet,DataRow,DataColumn,DataRelation,Constraint,DataColumnMapping,DataTableMapping②System.Data.Coummon → 各種數據訪問類的基類和介面③Sys ...
  • 接觸到了一個開發需求。其中是要把NC單據表體行的欄位拼成一個字元串。例如: 出現結果字元串為:name:王一,李二,張三 語句+效果: ...
  • 《.Net程式員學用Oracle系列:導航目錄》 本文大綱 1、 " 觸發器 " 1.1、 "創建觸發器" 1.2、 "禁用觸發器 & 啟用觸發器 & 刪除觸發器" 2、 " 任務 " 2.1、 "DBMS_JOB 包介紹" 3、 " 序列 " 3.1、 "創建序列" 3.2、 "使用序列 & 刪除 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...