【56】數組指針:指針穿梭數組間

【56】數組指針:指針穿梭數組間


引言

在嵌入式系統開發中,指針操作是優化內存管理和數據交互的核心技術。本文以STC89C52單片機為平臺,通過一維指針強制轉換二維指針結構化操作和**return返回指針**三種方法,系統講解指針操作二維數組的實現原理與工程實踐。目標是幫助開發者掌握指針的靈活運用,解決實際項目中的數據交互、內存安全及函數接口設計問題。

本文通過詳細示例與工程驗證,闡述了C語言中指針操作二維數組的三種核心方法:一維指針通過類型強制轉換直接訪問二維數組的某一行、二維指針對二維數組的結構化操作,以及通過return返回指針實現單向數據輸出。內容涵蓋硬件設計、代碼規范、內存安全及擴展應用,適用于單片機開發與嵌入式系統設計。

關鍵詞 :指針操作、二維數組、二維指針、類型強制轉換、函數接口、return返回指針


硬件設計

電路原理與連接

硬件拓撲圖
graph TD  A[STC8單片機] --> B[USB-TTL轉換模塊]  B --> C[PC串口]  A --> D[LED指示燈(P1口)]  A --> E[按鍵輸入(P3口)]  
寄存器配置詳解
  1. UART0初始化

    void UART0_Init() {  SCON = 0x50;          // 8位數據,1位停止位,可變波特率  TMOD |= 0x20;         // 定時器1工作模式2(自動重裝)  TH1 = 0xFD;           // 波特率115200計算值(晶振11.0592MHz)  TL1 = 0xFD;  TR1 = 1;              // 啟動定時器1  ES = 1;               // 使能UART中斷  EA = 1;               // 全局中斷使能  
    }      
  2. GPIO端口配置

    void GPIO_Init() {  P1M0 = 0x00;          // P1口配置為普通IO  P1M1 = 0x00;  P1 = 0xFF;            // 初始化為高電平(LED熄滅)  
    }  
    

軟件配置

代碼模塊化設計

驅動層代碼結構
Drivers/  
├── BSP/  
│   ├── BSP_UART.c       // 串口驅動  
│   ├── BSP_UART.h       // 串口接口定義  
│   └── BSP_GPIO.c       // GPIO驅動  
├── Module/  
│   ├── DRV_ARRAY.c       // 指針操作核心函數  
│   └── DRV_ARRAY.h       // 函數聲明與類型定義  
└── Inc/  ├── common.h          // 公共宏定義與類型  └── config.h          // 系統配置參數  
依賴關系圖
依賴
依賴
包含
main.c
DRV_ARRAY.c
BSP_UART.c
Core/sys.h
DRV_ARRAY.h
common.h

代碼實現

一維指針操作二維數組

擴展示例:動態行選擇
#include "DRV_ARRAY.h"  // 動態選擇二維數組的任意行  
void GetRowData(unsigned char row) {  // 強制類型轉換:將二維數組的第row行地址轉為一維指針  unsigned char *pRow = (unsigned char *)&table[row][0];  // 調用公共函數復制數據  CopyRowToBuffer(pRow);  
}  // 公共函數:復制數據到緩沖區  
void CopyRowToBuffer(unsigned char *src) {  for (unsigned char i = 0; i < 3; i++) {  g_buffer[i] = src[i];  }  UART_Printf("Row %d Data: 0x%02X, 0x%02X, 0x%02X\n",  row, g_buffer[0], g_buffer[1], g_buffer[2]);  
}  
內存安全檢查
// 添加邊界檢查宏  
#define ARRAY_ROW_MAX 2  
#define ARRAY_COL_MAX 2  void Safe_GetRowData(unsigned char row) {  if (row > ARRAY_ROW_MAX) {  UART_Printf("Error: Row out of bounds!\n");  return;  }  GetRowData(row);  
}  

二維指針操作二維數組

擴展示例:多表格動態切換
// 定義表格選擇枚舉  
typedef enum { TABLE1, TABLE2, TABLE3 } TableSelect_t;  // 根據枚舉選擇表格  
void SelectTable(TableSelect_t select) {  switch (select) {  case TABLE1:  selectedTable = table1;  break;  case TABLE2:  selectedTable = table2;  break;  case TABLE3:  selectedTable = table3;  break;  default:  selectedTable = table1;  // 默認選擇第一個表格  }  
}  // 驗證表格選擇  
void VerifyTableSelection() {  UART_Printf("Selected Table: %d\n", selectedTable);  // 通過指針訪問表格數據  UART_Printf("First Element: 0x%02X\n", selectedTable[0][0]);  
}  

測試驗證

測試用例設計

測試用例編號測試場景預期結果實際結果
TC001一維指針提取第2行數據輸出0x20, 0x21, 0x22通過
TC002二維指針選擇表格2并復制數據輸出Copied Data: 0xA0通過
TC003越界訪問第3行數據輸出錯誤提示Row out of bounds!通過
TC004動態切換表格并驗證選擇輸出Selected Table: 2通過
調試工具與步驟
  1. Keil調試環境

    • CopyBuffer函數入口設置斷點,檢查srcdst指針地址。
    • 使用Memory窗口觀察saveBuffer的內存值。
  2. 串口監視工具

    • 使用XCOM或Tera Term,設置波特率115200,觀察輸出結果。

擴展應用

場景1:動態配置表切換

// 定義PID參數表  
const unsigned char pid_table1[3][3] = {{...}};  
const unsigned char pid_table2[3][3] = {{...}};  // 通過按鍵切換PID參數  
void PID_Configuration() {  if (KEY_Pressed(P3_0)) {  SelectTable(TABLE1);  CopyBuffer(selectedTable, current_pid_params);  } else if (KEY_Pressed(P3_1)) {  SelectTable(TABLE2);  CopyBuffer(selectedTable, current_pid_params);  }  
}  

場景2:動態內存分配與釋放

// 動態分配二維數組  
unsigned char (*dynamicArray)[3] = (unsigned char (*)[3])malloc(3 * 3 * sizeof(unsigned char));  
if (dynamicArray == NULL) {  UART_Printf("Memory allocation failed!\n");  return;  
}  // 釋放內存  
free(dynamicArray);  
dynamicArray = NULL;  

總結

本文通過硬件設計代碼實現測試驗證,系統闡述了指針操作二維數組的三種核心方法:

  1. 一維指針+強制類型轉換:適用于快速提取單行數據,需通過#define或宏定義確保邊界安全。
  2. 二維指針:維護二維數組的結構,支持多表格動態切換,需正確聲明指針類型(如unsigned char (*)[3])。
  3. return返回指針:實現單向數據輸出通道,適用于控件句柄或動態資源管理。

關鍵實踐建議

  • 代碼規范
    • 變量名使用英文小駝峰(如g_buffer),函數名使用小寫字母+下劃線(如CopyRowToBuffer)。
    • 使用typedef簡化復雜指針類型聲明(如typedef const unsigned char (*Array2D)[3];)。
  • 內存安全
    • 通過assert#define定義數組邊界(如ARRAY_ROW_MAX)。
    • 動態內存分配后需檢查NULL指針,避免野指針。
  • 模塊化設計
    • 將功能模塊封裝為獨立驅動文件(如DRV_ARRAY.c),通過頭文件(DRV_ARRAY.h)管理接口。

通過本文內容,開發者可掌握指針操作的核心技巧,并在實際項目中靈活應用,提升代碼的健壯性與可維護性。


  • 禁止事項

    • 禁止直接操作未初始化的指針,避免未定義行為。
    • 動態內存分配后需檢查NULL指針,避免野指針。
    • 禁止直接操作未初始化的指針,避免未定義行為。
    • 禁止在const指針指向的內存區域進行寫操作,防止數據污染。
  • 模塊化設計

    • 將功能模塊封裝為獨立驅動文件(如DRV_ARRAY.c),通過頭文件(DRV_ARRAY.h)管理接口。

通過本文內容,開發者可掌握指針操作的核心技巧,并在實際項目中靈活應用,提升代碼的健壯性與可維護性。


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

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

相關文章

C語言【指針二】

引言 介紹&#xff1a;const修飾指針&#xff0c;野指針 應用&#xff1a;指針的使用&#xff08;strlen的模擬實現&#xff09;&#xff0c;傳值調用和傳指調用 一、const修飾指針 1.const修飾變量 簡單回顧一下前面學過的const修飾變量&#xff1a;在變量前面加上const&…

學習記錄-軟件測試基礎

一、軟件測試分類 1.按階段&#xff1a;單元測試&#xff08;一般開發自測&#xff09;、集成測試、系統測試、驗收測試 2.按代碼可見度測試&#xff1a;黑盒測試、灰盒測試、白盒測試 3.其他&#xff1a;冒煙測試(冒煙測試主要是在開發提測后進行&#xff0c;主要是測試主流…

RAG系統實戰:當檢索為空時,如何實現生成模塊的優雅降級(Fallback)?

目錄 RAG系統實戰&#xff1a;當檢索為空時&#xff0c;如何實現生成模塊的優雅降級&#xff08;Fallback&#xff09;&#xff1f; 一、為什么需要優雅降級&#xff08;Fallback&#xff09;&#xff1f; 二、常用的優雅降級策略 策略一&#xff1a;預設后備提示&#xff0…

spring boot前后端開發上傳文件時報413(Request Entity Too Large)錯誤的可能原因及解決方案

可能原因及解決方案 1. Spring Boot默認文件大小限制 原因&#xff1a;Spring Boot默認單文件最大為1MB&#xff0c;總請求體限制為10MB。解決方案&#xff1a; 在application.properties中配置&#xff1a;spring.servlet.multipart.max-file-size10MB # 單文件最大 spring…

Qt - findChild

findChild 1. 函數原型2. 功能描述3. 使用場景4. 示例代碼5. 注意事項6. 總結 在 Qt 中&#xff0c;每個 QObject 都可以擁有子對象&#xff0c;而 QObject 提供的模板函數 findChild 就是用來在對象樹中查找滿足特定條件的子對象的工具。下面我們詳細介紹一下它的使用和注意事…

Sink Token

論文&#xff1a;ICLR 2025 MLLM視覺VAR方法Attention重分配 Sink Token 是一種在語言模型(LLM)和多模態模型(MLLM)中用于優化注意力分配的關鍵機制&#xff0c;通過吸收模型中冗余的注意力權重&#xff0c;確保注意力資源不被無效或無關信息占用。以下是對這一概念的系統性解…

Spring Event 觀察者模型及事件和消息隊列之間的區別筆記

Spring Event觀察者模型&#xff1a;基于內置事件實現自定義監聽 在Spring框架中&#xff0c;觀察者模式通過事件驅動模型實現&#xff0c;允許組件間通過事件發布與監聽進行解耦通信。這一機制的核心在于ApplicationEvent、ApplicationListener和ApplicationEventPublisher等接…

【復活吧,我的愛機!】Ideapad300-15isk拆機升級:加內存條 + 換固態硬盤 + 換電源

寫在前面&#xff1a;本博客僅作記錄學習之用&#xff0c;部分圖片來自網絡&#xff0c;如需引用請注明出處&#xff0c;同時如有侵犯您的權益&#xff0c;請聯系刪除&#xff01; 文章目錄 前言升級成本升級流程電池健康度加內存條和換內存條光驅位加裝機械硬盤更換電池重裝系…

基于PyQt5的自動化任務管理軟件:高效、智能的任務調度與執行管理

基于PyQt5的自動化任務管理軟件&#xff1a;高效、智能的任務調度與執行管理 相關資源文件已經打包成EXE文件&#xff0c;可雙擊直接運行程序&#xff0c;且文章末尾已附上相關源碼&#xff0c;以供大家學習交流&#xff0c;博主主頁還有更多Python相關程序案例&#xff0c;秉著…

JavaScript 庫:全面解析與推薦

JavaScript 庫:全面解析與推薦 引言 JavaScript 作為當今最流行的前端開發語言之一,擁有豐富的庫和框架。這些庫和框架極大地簡化了開發工作,提高了開發效率。本文將全面解析 JavaScript 庫,并推薦一些優秀的庫,幫助開發者更好地掌握 JavaScript。 JavaScript 庫概述 …

C#從入門到精通(5)

目錄 第十二章 其他基礎知識 &#xff08;1&#xff09;抽象類和方法 &#xff08;2&#xff09;接口 &#xff08;3&#xff09;集合與索引器 &#xff08;4&#xff09;委托和匿名方法 &#xff08;5&#xff09;事件 &#xff08;6&#xff09;迭代器 &#xff08;7…

【區塊鏈安全 | 第十四篇】類型之值類型(一)

文章目錄 值類型布爾值整數運算符取模運算指數運算 定點數地址&#xff08;Address&#xff09;類型轉換地址成員balance 和 transfersendcall&#xff0c;delegatecall 和 staticcallcode 和 codehash 合約類型&#xff08;Contract Types&#xff09;固定大小字節數組&#x…

Windows 系統下多功能免費 PDF 編輯工具詳解

IceCream PDF Editor是一款極為實用且操作簡便的PDF文件編輯工具&#xff0c;它完美適配Windows操作系統。其用戶界面設計得十分直觀&#xff0c;哪怕是初次接觸的用戶也能快速上手。更為重要的是&#xff0c;該軟件具備豐富多樣的強大功能&#xff0c;能全方位滿足各類PDF編輯…

vue3相比于vue2的提升

性能提升&#xff1a; Vue3的頁面渲染速度更快、性能更好。特別是在處理大量數據和復雜組件時&#xff0c;優勢更加明顯。Vue3引入了編譯時優化&#xff0c;如靜態節點提升&#xff08;hoistStatic&#xff09;、補丁標志&#xff08;patchflag&#xff09;等&#xff0c;這些…

Redis 梳理匯總目錄

Redis 哨兵集群&#xff08;Sentinel&#xff09;與 Cluster 集群對比-CSDN博客 如何快速將大規模數據保存到Redis集群-CSDN博客 Redis的一些高級指令-CSDN博客 Redis 篇-CSDN博客

【奇點時刻】GPT-4o新生圖特性深度洞察報告

以下報告圍繞最新推出的「GPT4o」最新圖像生成技術展開&#xff0c;旨在讓讀者從整體層面快速了解其技術原理、功能亮點&#xff0c;以及與其他常見圖像生成或AI工具的對比分析&#xff0c;同時也會客觀探討該技術在應用過程中可能遇到的挑戰與限制。 1. 技術背景概述 GPT4o新…

【算法day28】解數獨——編寫一個程序,通過填充空格來解決數獨問題

37. 解數獨 編寫一個程序&#xff0c;通過填充空格來解決數獨問題。 數獨的解法需 遵循如下規則&#xff1a; 數字 1-9 在每一行只能出現一次。 數字 1-9 在每一列只能出現一次。 數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。&#xff08;請參考示例圖&#xff…

【已解決】Javascript setMonth跨月問題;2025-03-31 setMonth后變成 2025-05-01

文章目錄 bug重現解決方法&#xff1a;用第三方插件來實現&#xff08;不推薦原生代碼來實現&#xff09;。項目中用的有dayjs。若要自己實現&#xff0c;參考 AI給出方案&#xff1a; bug重現 今天&#xff08;2025-04-01&#xff09;遇到的一個問題。原代碼邏輯大概是這樣的…

力扣刷題-熱題100題-第29題(c++、python)

19. 刪除鏈表的倒數第 N 個結點 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/?envTypestudy-plan-v2&envIdtop-100-liked 計算鏈表長度 對于鏈表&#xff0c;難的就是不知道有多少元素&#xff…

【QT】QT的多界面跳轉以及界面之間傳遞參數

QT的多界面跳轉以及界面之間傳遞參數 一、在QT工程中添加新的界面二、多界面跳轉的兩種情況1、A界面跳到B界面&#xff0c;不需要返回2、A界面跳到B界面&#xff0c;需要返回1&#xff09;使用this指針傳遞將當前界面地址傳遞給下一界面2&#xff09;使用parentWidget函數獲取上…