深入理解指針(3)(C語言版)

文章目錄

      • 前言
    • 一、字符指針變量
    • 二、數組指針變量
      • 2.1 數組指針變量是什么
      • 2.2 數組指針變量怎么初始化
        • 2.2.1 靜態初始化
        • 2.2.2 動態初始化
    • 三、二維數組傳參的本質
    • 四、函數指針變量
      • 4.1 函數指針變量的創建
      • 4.2 函數指針變量的使用
      • 4.3 typedef關鍵字
      • 4.4拓展
    • 五、函數指針數組
    • 六、轉移表
    • 總結

前言

在C語言中,指針一直是一個讓初學者頭疼的話題。它看似復雜難懂,但其實只要掌握了正確的方法,就能輕松駕馭。在之前的兩篇博客中,我們已經對指針有了初步的認識。今天,我們將繼續深入探索指針的更多奧秘。
在這里插入圖片描述

一、字符指針變量

字符指針變量是用來存儲字符數組(字符串)首地址的變量。它的聲明方式是char *指針變量名;。例如:

char *str = "Hello, World!";

這里,str就是一個字符指針變量,它指向了字符串"Hello, World!"的首地址。通過字符指針變量,我們可以對字符串進行操作。比如,printf("%s", str);就可以輸出整個字符串。

二、數組指針變量

2.1 數組指針變量是什么

數組指針變量是用來存儲數組首地址的變量。它的聲明方式是類型 (*指針變量名)[數組長度];。例如:

int arr[5] = {1, 2, 3, 4, 5};
int (*p)[5] = &arr;

這里,p就是一個指向包含5個整數的數組的指針變量。它指向了數組arr的首地址。通過數組指針變量,我們可以訪問數組中的元素。比如,printf("%d", (*p)[2]);就可以輸出數組中的第三個元素3。

數組指針變量與普通指針變量的區別在于,數組指針變量指向的是一個數組,而普通指針變量指向的是一個單一的變量或一個字符串。數組指針變量在內存中占用的空間比普通指針變量大,因為它需要存儲整個數組的地址信息。

2.2 數組指針變量怎么初始化

數組指針變量的初始化可以通過以下兩種方式:

2.2.1 靜態初始化

在聲明數組指針變量時,直接將其初始化為一個已知數組的地址。例如:

int arr[5] = {1, 2, 3, 4, 5};
int (*p)[5] = &arr;

這里,p被初始化為指向數組arr的首地址。

2.2.2 動態初始化

在程序運行過程中,通過malloc函數動態分配一個數組,并將數組指針變量初始化為分配的內存地址。例如:

int (*p)[5] = (int (*)[5])malloc(sizeof(int) * 5);
if (p == NULL) {printf("Memory allocation failed\n");exit(1);
}
for (int i = 0; i < 5; i++) {(*p)[i] = i + 1;
}

這里,p被動態分配了一個包含5個整數的數組,并通過循環初始化了數組中的元素。

三、二維數組傳參的本質

在C語言中,當我們把二維數組作為參數傳遞給函數時,實際上傳遞的是數組首地址。函數接收的是一個指向一維數組的指針。例如:

void printArray(int arr[][3], int rows) {for (int i = 0; i < rows; i++) {for (int j = 0; j < 3; j++) {printf("%d ", arr[i][j]);}printf("\n");}
}

這里,arr是一個指向包含3個整數的一維數組的指針。通過這種方式,我們可以在函數中操作二維數組。

四、函數指針變量

4.1 函數指針變量的創建

函數指針變量是用來存儲函數地址的變量。它的聲明方式是返回類型 (*指針變量名)(參數列表);。例如:

int add(int a, int b) {return a + b;
}int (*funcPtr)(int, int) = add;

這里,funcPtr就是一個指向add函數的指針變量。通過函數指針變量,我們可以調用函數。比如,printf("%d", (*funcPtr)(1, 2));就可以輸出3。

4.2 函數指針變量的使用

函數指針變量的使用非常靈活,可以用于多種場景。例如,我們可以根據不同的條件調用不同的函數:

int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }int (*funcPtr)(int, int);int choice;
printf("Enter your choice (1 for add, 2 for sub): ");
scanf("%d", &choice);if (choice == 1) {funcPtr = add;
} else if (choice == 2) {funcPtr = sub;
} else {printf("Invalid choice\n");return 1;
}printf("%d\n", (*funcPtr)(5, 3));

這里,根據用戶輸入的選擇,程序會調用addsub函數。

4.3 typedef關鍵字

typedef關鍵字可以用來為數據類型定義一個別名,包括函數指針類型。例如:

typedef int (*FuncPtr)(int, int);FuncPtr funcPtr = add;

這里,FuncPtrint (*funcPtr)(int, int)的別名。通過typedef,我們可以簡化函數指針的聲明,使代碼更加清晰易讀。

4.4拓展

兩段來自《C陷阱和缺陷》有趣的代碼

五、函數指針數組

函數指針數組是一個數組,其元素都是函數指針。它的聲明方式是返回類型 (*指針數組名[數組長度])(參數列表);。例如:

int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }
int div(int a, int b) { return a / b; }int (*funcPtrArr[4])(int, int) = {add, sub, mul, div};

這里,funcPtrArr就是一個包含4個函數指針的數組。通過函數指針數組,我們可以根據不同的條件調用不同的函數。比如:

for (int i = 0; i < 4; i++) {printf("%d ", (*funcPtrArr[i])(4, 2));
}

輸出結果為6 2 8 2。

六、轉移表

轉移表是一種利用函數指針數組實現的控制結構。它根據不同的輸入條件,選擇執行不同的函數。例如,在一個簡單的菜單系統中,我們可以使用轉移表來實現不同的功能選項:

void option1() { printf("Option 1\n"); }
void option2() { printf("Option 2\n"); }
void option3() { printf("Option 3\n"); }void (*transferTable[3])() = {option1, option2, option3};int choice;
printf("Enter your choice (1-3): ");
scanf("%d", &choice);if (choice >= 1 && choice <= 3) {transferTable[choice - 1]();
} else {printf("Invalid choice\n");
}

這里,根據用戶輸入的選擇,程序會調用對應的函數。

總結

通過本篇博客的學習,我們深入理解了字符指針變量、數組指針變量、二維數組傳參的本質、函數指針變量、函數指針數組以及轉移表等指針的高級應用。指針是C語言中非常強大的工具,它能讓我們的程序更加靈活和高效。希望讀者能夠通過不斷地實踐和思考,真正掌握指針的精髓。

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

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

相關文章

Linux之 權限提升(Linux Privilege Escalation)

Linux 之權限提升 系統信息 1.獲取操作系統信息 2.檢查PATH&#xff0c;是否有任何可寫的文件夾&#xff1f; 3.檢查環境變量&#xff0c;有任何敏感細節嗎&#xff1f; 4.使用腳本&#xff08;DirtyCow&#xff1f;&#xff09;搜索內核漏洞 5.檢查sudo 版本是否存在漏洞…

【leetcode hot 100 215】數組中的第K個最大元素

解法一&#xff1a;維護最大最小值 -> 堆 -> k個元素的最小值堆 class Solution {public int findKthLargest(int[] nums, int k) {// 維護最大最小值 -> 堆 -> k個元素的最小值堆PriorityQueue<Integer> heap new PriorityQueue<>((n1, n2) -> n…

csp信奧賽C++常用的數學函數詳解

csp信奧賽C常用的數學函數詳解 在信息學奧林匹克競賽&#xff08;信奧賽&#xff09;中&#xff0c;C 的 <cmath> 頭文件提供了豐富的數學函數&#xff0c;用于高效處理數學運算。以下是常用系統數學函數的詳細講解及匯總表格。 絕對值函數 int abs(int x)&#xff1a;返…

Java IntelliJ IDEA 中配置多個 JDK 版本

目錄 一、添加多個 JDK 版本1. 下載并安裝多個 JDK 版本2. 配置 JDK 在 IntelliJ IDEA 中 二、在項目中切換 JDK 版本1. 設置項目使用的 JDK 版本2. 設置模塊使用的 JDK 版本 三、在運行配置中指定 JDK 版本四、總結 在實際開發中&#xff0c;我們常常需要在同一個項目中使用不…

ChatDBA VS DeepSeek:快速診斷 OceanBase 集群新租戶數據同步異常

社區王牌專欄《一問一實驗&#xff1a;AI 版》改版以來已發布多期&#xff08;51-60&#xff09;&#xff0c;展現了 ChatDBA 在多種場景下解決問題的效果。 下面讓我們正式進入《一問一實驗&#xff1a;AI 版》第 62 期&#xff0c;看看 ChatDBA 最新效果以及與熱門大模型 De…

Java條碼與二維碼生成技術詳解

一、技術選型分析 1.1 條碼生成方案 Barbecue是最成熟的Java條碼庫&#xff0c;支持&#xff1a; Code 128EAN-13/UPC-AUSPS Inteligent Mail等12種工業標準格式 1.2 二維碼方案對比 庫名稱維護狀態復雜度功能擴展性ZXing★★★★☆較高強QRGen★★★☆☆簡單一般BoofCV★…

air780eq 阿里云

硬件&#xff1a;APM32F030C8 Air 780eq 參考文檔&#xff1a; 合宙780E-4G模塊通過AT指令連接到阿里云平臺&#xff0c;實現信息的收發_air780e上傳阿里云屬性值at命令-CSDN博客 阿里云 - atair780eq - 合宙文檔中心 4G模塊接入阿里云-實現數據上傳和命令下發_4g模塊上傳…

oracle數據庫(數據庫啟動關閉/sqlplus登錄及基本操作/設置字符集/distinct去重)

目錄 1. Oracle數據庫啟動 2. Oracle數據庫關閉 3. sqlplus登錄Oracle數據庫 3.1 使用sqlplus登錄Oracle數據庫 3.2 使用sqlplus登錄Oracle數據庫 3.3 遠程登錄 3.4 解鎖用戶 3.5 修改用戶密碼 3.6 查看當前語言環境 4. sqlplus基本操作 4.1 顯示當前用戶 4.2 查看當前用戶…

Java 大視界 -- Java 大數據在智能金融區塊鏈跨境支付與結算中的應用(154)

&#x1f496;親愛的朋友們&#xff0c;熱烈歡迎來到 青云交的博客&#xff01;能與諸位在此相逢&#xff0c;我倍感榮幸。在這飛速更迭的時代&#xff0c;我們都渴望一方心靈凈土&#xff0c;而 我的博客 正是這樣溫暖的所在。這里為你呈上趣味與實用兼具的知識&#xff0c;也…

大模型詞表注入

大模型詞表注入&#xff08;Vocabulary Injection&#xff09; 大模型詞表注入&#xff08;Vocabulary Injection&#xff09;是指在預訓練語言模型&#xff08;如GPT、LLAMA等&#xff09;的基礎上&#xff0c;動態擴展其詞表&#xff08;Vocabulary&#xff09;的技術&#…

在Cesium中使用ThreeJs材質(不是場景融合哦)

在Cesium中使用ThreeJs材質(不是場景融合哦&#xff09;_嗶哩嗶哩_bilibili

初教六雙機一飛沖天動作要領

初教六雙機一飛沖天動作要領 初教六雙機“一飛沖天”是典型的垂直爬升特技動作&#xff0c;要求雙機以近乎垂直的姿態同步高速爬升&#xff0c;展現飛機的動力性能與編隊協同能力。以下是該動作的詳細技術解析與執行要點&#xff1a; 一、動作定義與特點 基本形態 雙機以相同速…

給Web開發者的HarmonyOS指南02-布局樣式

給Web開發者的HarmonyOS指南02-布局樣式 本系列教程適合鴻蒙 HarmonyOS 初學者&#xff0c;為那些熟悉用 HTML 與 CSS 語法的 Web 前端開發者準備的。 本系列教程會將 HTML/CSS 代碼片段替換為等價的 HarmonyOS/ArkUI 代碼。 布局基礎對比 在Web開發中&#xff0c;我們使用CS…

京東軟件測試崗位經典面試題(附答案)

1、黑盒測試的測試用例常見設計方法都有哪些&#xff1f;請分別以具體的例子來說明這些方法在測試用例設計工作中的應用。 1&#xff09;等價類劃分&#xff1a;等價類是指某個輸入域的子集合.在該子集合中&#xff0c;各個輸入數據對于揭露程序中的錯誤都是等效的.并合理地假…

3.26[a]paracompute homework

5555 負載不平衡指多個線程的計算量差異顯著&#xff0c;導致部分線程空轉或等待&#xff0c;降低并行效率。其核心矛盾在于任務劃分的靜態性與計算動態性不匹配&#xff0c;尤其在處理不規則數據或動態任務時尤為突出。以稀疏矩陣的向量乘法為例&#xff0c;假設其非零元素分…

網站安全專欄-------淺談CC攻擊和DDoS攻擊的區別

CC攻擊和DDoS攻擊都是網絡攻擊的類型&#xff0c;但它們在攻擊方式、目標和效果上有所不同。以下是它們之間的一些主要區別&#xff1a; ### 1. 定義 - **DDoS攻擊&#xff08;分布式拒絕服務攻擊&#xff09;**&#xff1a; DDoS攻擊是指攻擊者通過大量的分布式計算機&#x…

帕金森患者的生活重塑:從 “嘴” 開啟康復之旅

當提到帕金森病&#xff0c;許多人會聯想到震顫、僵硬和行動遲緩等癥狀。這種神經系統退行性疾病&#xff0c;給患者的生活帶來了巨大的挑戰。然而&#xff0c;你可知道&#xff0c;帕金森患者恢復正常生活&#xff0c;可以從 “嘴” 開始管理&#xff1f; 帕金森病在全球影響著…

Android14 Settings應用添加有線網開關條目實現

Android14 Settings應用添加有線網開關條目 文章目錄 Android14 Settings應用添加有線網開關條目一、前言二、適配修改1、network_provider_settings.xml2、NetworkProviderSettings.java3、TurnOnOffEthernetNetworkController.java4、去除有線網提示條目。5、效果UI&#xff…

Axure RP設計軟件中的各種函數:包括數字、數學、字符串、時間及中繼器函數,詳細解釋了各函數的用途、參數及其應用場景。

文章目錄 引言函數分類數字函數數學函數字符串函數時間函數函數中繼器函數引言 在axure交互設計時,函數可以用在條件公式和需要賦值的地方,其基本語法是用雙方括號包含,變量值和函數用英文句號連接。 在交互事件編輯器中通過fx按鈕插入函數表達式,例如設置文本內容為: …

c#難點整理3

1.靜態類的說明 a.靜態類里不能定義實例方法&#xff0c;實例屬性&#xff0c;所以說非靜態類是無法繼承靜態類的。父類無法擁有實例化的方法和屬性&#xff0c;子類可以&#xff0c;這從邏輯上是矛盾的&#xff0c;不符合繼承的邏輯。 b.那么靜態類與靜態類之間能否繼承能呢…