程序詩篇里的靈動筆觸:指針繪就數據的夢幻藍圖<6>

在這里插入圖片描述

大家好啊,我是小象?(?òωó?)?
我的博客:Xiao Xiangζ?????

很高興見到大家,希望能夠和大家一起交流學習,共同進步
在這里插入圖片描述
今天我們繼續來學習數組指針變量,二維數組傳參的本質,函數指針變量,typedef關鍵字,函數指針數組,轉移表…

目錄

  • 數組指針變量
    • 1.1 數組指針變量是什么?
    • 1.2 數組指針變量怎么初始化
  • 二、二維數組傳參的本質
  • 三、 函數指針變量
    • 3.1 函數指針變量的創建
    • 3.2 函數指針變量的使用
    • 3.3.1 typedef 關鍵字
  • 四、函數指針數組
  • 五、轉移表
  • 六、結尾

數組指針變量

1.1 數組指針變量是什么?

在C語言中,數組指針變量(也叫指向數組的指針)是一種特殊的指針變量,它指向的是一個數組。
之前我們學習了指針數組,指針數組是?種數組,數組中存放的是地址(指針)。
數組指針變量是指針變量?還是數組?
答案是:指針變量。
我們已經熟悉:
? 整形指針變量: int * pint; 存放的是整形變量的地址,能夠指向整形數據的指針。
? 浮點型指針變量: float * pf; 存放浮點型變量的地址,能夠指向浮點型數據的指針。
那數組指針變量應該是:存放的應該是數組的地址,能夠指向數組的指針變量。
形式:

int (*p)[5];

這里定義了一個名為p的指針變量,它指向一個包含5個int類型元素的數組。注意,(p)兩邊的括號不能省略,因為[]的優先級高于,如果沒有括號int *p[5]; 這定義的是一個指針數組(一個包含5個int指針的數組),而不是指向數組的指針。

解釋:p先和結合,說明p是?個指針變量,然后指針指向的是?個大小為5個整型的數組。所以p是
?個指針,指向?個數組,叫 數組指針。
這?要注意:[]的優先級要?于
號的,所以必須加上()來保證p先和*結合。

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

數組指針變量是用來存放數組地址的,那怎么獲得數組的地址呢?就是我們之前學習的 &數組名 。

int arr[10] = {0};
&arr;//得到的就是數組的地址

如果要存放個數組的地址,就得存放在數組指針變量中,如下:

int(*p)[10] = &arr;

我們調試也能看到 &arr 和 p 的類型是完全?致的。
數組指針類型解析:

int (*p) [10] = &arr;| | || | || | p指向數組的元素個數| p是數組指針變量名p指向的數組的元素類型

二、二維數組傳參的本質

二維數組傳參的本質是傳遞指向一維數組的指針,函數通過這個指針和已知的列數信息,按照連續內存存儲的方式來訪問和處理二維數組中的元素

有了數組指針的理解,我們就能夠講?下二維數組傳參的本質了。
過去我們有?個二維數組的需要傳參給?個函數的時候,我們是這樣寫的:

#include <stdio.h>
void test(int a[3][5], int r, int c)
{int i = 0;int j = 0;for (i = 0; i < r; i++)
{for (j = 0; j < c; j++){printf("%d ", a[i][j]);}printf("\n");
}
}
int main()
{int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7} };test(arr, 3, 5);return 0;
}

這?實參是?維數組,形參也寫成?維數組的形式,那還有什么其他的寫法嗎?
?先我們再次理解?下?維數組,?維數組其實可以看做是每個元素是?維數組的數組,也就是?維數組的每個元素是?個?維數組。那么?維數組的?元素就是第??,是個?維數組。
所以,根據數組名是數組?元素的地址這個規則,?維數組的數組名表?的就是第??的地址,是?維數組的地址。根據上?的例?,第??的?維數組的類型就是 int [5] ,所以第??的地址的類型就是數組指針類型 int(*)[5] 。那就意味著?維數組傳參本質上也是傳遞了地址,傳遞的是第??這個?維數組的地址,那么形參也是可以寫成指針形式的。如下:

#include <stdio.h>
void test(int (*p)[5], int r, int c)
{int i = 0;int j = 0;for (i = 0; i < r; i++){for (j = 0; j < c; j++){printf("%d ", *(*(p + i) + j));}printf("\n");}
}
int main()
{int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7} };test(arr, 3, 5);return 0;
}

總結:?維數組傳參,形參的部分可以寫成數組,也可以寫成指針形式。

三、 函數指針變量

3.1 函數指針變量的創建

什么是函數指針變量呢?
根據前?學習整型指針,數組指針的時候,我們的類?關系,我們不難得出結論:
函數指針變量應該是?來存放函數地址的,未來通過地址能夠調?函數的。
那么函數是否有地址呢?
我們做個測試:

#include <stdio.h>
void test()
{printf("hehe\n");
}
int main()
{printf("test: %p\n", test);printf("&test: %p\n", &test);return 0;
}

結果:

test: 005913CA
&test: 005913CA

確實打印出來了地址,所以函數是有地址的,函數名就是函數的地址,當然也可以通過 &函數名 的?式獲得函數的地址。
如果我們要將函數的地址存放起來,就得創建函數指針變量咯,函數指針變量的寫法其實和數組指針?常類似。如下:

void test()
{printf("hehe\n");
}
void (*pf1)() = &test;
void (*pf2)() = test;
int Add(int x, int y)
{return x + y;
}
int(*pf3)(int, int) = Add;
int(*pf3)(int x, int y) = &Add;//x和y寫上或者省略都是可以的

函數指針類型解析:

int (*pf3) (int x, int y)| | ------------ | | || | pf3指向函數的參數類型和個數的交代| 函數指針變量名pf3指向函數的返回類型
int (*) (int x, int y) //pf3函數指針變量的類型

3.2 函數指針變量的使用

通過函數指針調?指針指向的函數。

include <stdio.h>
int Add(int x, int y)
{return x + y;
}
int main()
{int(*pf3)(int, int) = Add;printf("%d\n", (*pf3)(2, 3));printf("%d\n", pf3(3, 5));return 0;
}

3.3.1 typedef 關鍵字

typedef 是?來類型重命名的,可以將復雜的類型,簡單化。
比如,你覺得 unsigned int 寫起來不?便,如果能寫成 uint 就?便多了,那么我們可以使?:

typedef unsigned int uint;
//將unsigned int 重命名為uint

如果是指針類型,能否重命名呢?其實也是可以的,?如,將 int* 重命名為 ptr_t ,這樣寫:

typedef int* ptr_t;

但是對于數組指針和函數指針稍微有點區別:
?如我們有數組指針類型 int(*)[5] ,需要重命名為 parr_t ,那可以這樣寫:

typedef int(*parr_t)[5]; //新的類型名必須在*的右邊

函數指針類型的重命名也是?樣的,?如,將 void(*)(int) 類型重命名為 pf_t ,就可以這樣寫:

typedef void(*pfun_t)(int);//新的類型名必須在*的右邊

那么要簡化代碼2,可以這樣寫:

typedef void(*pfun_t)(int);
pfun_t signal(int, pfun_t);

四、函數指針數組

數組是?個存放相同類型數據的存儲空間,我們已經學習了指針數組,

int * arr[10];
//數組的每個元素是int*

那要把函數的地址存到?個數組中,那這個數組就叫函數指針數組,那函數指針的數組如何定義呢?

int (*parr1[3])();
int *parr2[3]();
int (*)() parr3[3];

五、轉移表

函數指針數組的?途:轉移表
舉例:計算器的?般實現:

#include <stdio.h>
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 main()
{int x, y;int input = 1;int ret = 0;do{printf("*************************\n");printf(" 1:add 2:sub \n");printf(" 3:mul 4:div \n");printf(" 0:exit \n");printf("*************************\n");printf("請選擇:");scanf("%d", &input);switch (input){case 1:printf("輸?操作數:");scanf("%d %d", &x, &y);ret = add(x, y);printf("ret = %d\n", ret);break;case 2:printf("輸?操作數:");scanf("%d %d", &x, &y);ret = sub(x, y);printf("ret = %d\n", ret);break;case 3:printf("輸?操作數:");scanf("%d %d", &x, &y);ret = mul(x, y);printf("ret = %d\n", ret);break;case 4:printf("輸?操作數:");scanf("%d %d", &x, &y);ret = div(x, y);printf("ret = %d\n", ret);break;case 0:printf("退出程序\n");break;default:printf("選擇錯誤\n");break;}} while (input);return 0;
}

使?函數指針數組的實現:

#include <stdio.h>
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 main()
{int x, y;int input = 1;int ret = 0;int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //轉移表do{printf("*************************\n");printf(" 1:add 2:sub \n");printf(" 3:mul 4:div \n");printf(" 0:exit \n");printf("*************************\n");printf("請選擇:");scanf("%d", &input);if ((input <= 4 && input >= 1)){printf("輸?操作數:");scanf("%d %d", &x, &y);ret = (*p[input])(x, y);printf("ret = %d\n", ret);}else if (input == 0){printf("退出計算器\n");}else{printf("輸?有誤\n");}} while (input);return 0;
}

六、結尾

這一課的內容就到這里了,下節課繼續學習指針的其他一些知識
如果內容有什么問題的話歡迎指正,有什么問題也可以問我!
在這里插入圖片描述

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

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

相關文章

MySQL時間類型相關總結(DATETIME, TIMESTAMP, DATE, TIME, YEAR)

MySQL時間類型相關總結(DATETIME, TIMESTAMP, DATE, TIME, YEAR) MySQL官方文檔&#xff1a; https://dev.mysql.com/doc/refman/8.0/en/date-and-time-types.html 一. 對比&#xff1a; 在 MySQL 中&#xff0c;處理時間相關的數據類型主要有以下幾種&#xff1a;DATE、TIME、…

前綴和練習——洛谷P8218:求區間和

題目: 這道題很簡單&#xff0c;直接根據題目無腦套公式 代碼&#xff1a; #include<bits/stdc.h> using namespace std; const int N 1e5 9; using ll long long; ll a[N], perfix[N]; int main() {ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);//取消同步輸…

【STM32】藍牙模塊數據包解析

使用到的藍牙模塊為DX-BT24&#xff0c;他可以將串口轉藍牙&#xff0c;實現與手機藍牙的通信&#xff0c;本次實現使用手機藍牙發送數據包來控制單片機LED的亮滅&#xff0c;規則如下&#xff1a; AA 05 01 FF AF 該數據包表示包頭為AA&#xff0c;05表示該數據包的大小&#…

NSS-DAY2

Crypto [HNCTF 2022 Week1]A dictator 題目&#xff1a; from random import randint from secret import flagoffset randint(1,100) % 26 # print(offset)assert flag.startswith(NSSCTF{) assert all([ord(c) not in range(ord(A),ord(Z)) for c in flag[7:-1]])for cha…

【vue3 入門到實戰】7. 標簽中的 ref

目錄 1. ref 的作用 2. 如何使用 1. ref 的作用 用于注冊模板引用 用在普通DOM標簽上&#xff0c;獲取的是DOM節點。 用在組件標簽上&#xff0c;獲取的是組件的實例對象。 2. 如何使用 代碼如下 <template><div class"app"><h2 ref"titl…

手寫MVVM框架-實現簡單的數據代理

MVVM框架最顯著的特點就是虛擬dom和響應式的數據、我們以Vue為例&#xff0c;分別實現data、computed、created、methods以及虛擬dom。 這一章我們先實現簡單的響應式&#xff0c;修改數據之后在控制臺打印。 我們將該框架命名為MiniVue。 首先我們需要創建MiniVue的類(src/co…

Redis命令:列表模糊刪除詳解

前言 在Redis中&#xff0c;列表&#xff08;List&#xff09;是一種非常常用的數據結構&#xff0c;允許存儲多個有序的元素。然而&#xff0c;在實際應用中&#xff0c;可能會遇到需要刪除列表中符合某種模式的元素的需求。本文將詳細介紹如何在Redis中實現列表的模糊刪除。…

spy-debugger + Charles 調試移動端/內嵌小程序H5

簡介說明&#xff1a; PC端可以用F12進行console等進行調試&#xff0c;但移動端App中使用webview就無法進行實時調試&#xff0c;針對這種情況 1. 安裝 全局安裝 spy-debugger sudo npm install spy-debugger -g // window不用加sudo2. spy-debugger 證書 其實spy-debugg…

【目標檢測】模型驗證:K-Fold 交叉驗證

K-Fold 交叉驗證 1、引言1.1 K 折交叉驗證概述 2、配置2.1 數據集2.2 安裝包 3、 實戰3.1 生成物體檢測數據集的特征向量3.2 K 折數據集拆分3.3 保存記錄3.4 使用 K 折數據分割訓練YOLO 4、總結 1、引言 我們將利用YOLO 檢測格式和關鍵的Python 庫&#xff08;如 sklearn、pan…

Android studio ternimal 中gradle 指令失效(gradle環境變量未配置)

默認gradle路徑&#xff1a;C:\Users\ylwj.gradle\wrapper\dists\gradle-8.10.2-bin\a04bxjujx95o3nb99gddekhwo\gradle-8.10.2\bin 環境變量-系統環境變量-雙擊path-配置上即可-注意重啟studio才會生效

Axure大屏可視化動態交互設計:解鎖數據魅力,引領決策新風尚

可視化組件/模板預覽&#xff1a;https://8dge09.axshare.com 一、大屏可視化技術概覽 在數據驅動決策的時代&#xff0c;大屏可視化技術憑借直觀、動態的展示方式&#xff0c;已成為眾多行業提升管理效率和優化決策過程的關鍵工具。它能夠將復雜的數據轉化為易于理解的圖形和…

Resnet 改進:嘗試在不同位置加入Transform模塊

目錄 1. TransformerBlock 2. resnet 3. 替換部分卷積層 4. 在特定位置插入Transformer模塊 5. 使用Transformer全局特征提取器 6. 其他 Tips:融入模塊后的網絡經過測試,可以直接使用,設置好輸入和輸出的圖片維度即可 1. TransformerBlock TransformerBlock是Transfo…

PromptSource和LangChain哪個更好

目錄 1. 設計目標與定位 PromptSource LangChain 2. 功能對比 3. 優缺點分析 PromptSource LangChain 4. 如何選擇&#xff1f; 5. 總結 PromptSource 和 LangChain 是兩個在自然語言處理&#xff08;NLP&#xff09;領域非常有用的工具&#xff0c;但它們的設計目標和…

MySQL調優02 - SQL語句的優化

SQL語句的優化 文章目錄 SQL語句的優化一&#xff1a;SQL優化的小技巧1&#xff1a;編寫SQL時的注意點1.1&#xff1a;查詢時盡量不要使用*1.2&#xff1a;連表查詢時盡量不要關聯太多表1.3&#xff1a;多表查詢時一定要以小驅大1.4&#xff1a;like不要使用左模糊或者全模糊1.…

langchain教程-12.Agent/工具定義/Agent調用工具/Agentic RAG

前言 該系列教程的代碼: https://github.com/shar-pen/Langchain-MiniTutorial 我主要參考 langchain 官方教程, 有選擇性的記錄了一下學習內容 這是教程清單 1.初試langchain2.prompt3.OutputParser/輸出解析4.model/vllm模型部署和langchain調用5.DocumentLoader/多種文檔…

如何實現網頁不用刷新也能更新

要實現用戶在網頁上不用刷新也能到下一題&#xff0c;可以使用 前端和后端交互的技術&#xff0c;比如 AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;、Fetch API 或 WebSocket 來實現局部頁面更新。以下是一個實現思路&#xff1a; 1. 使用前端 AJAX 或 Fetch…

在ubuntu22.04上先部署docker,再編譯安裝kamailio,附詳細操作流程及docker和makailio的版本號

以下是在Ubuntu 22.04上部署Docker并編譯安裝Kamailio的詳細操作流程&#xff0c;包含版本號信息&#xff1a; 一、部署Docker&#xff08;版本&#xff1a;24.0.7&#xff09; 更新系統包 sudo apt update && sudo apt upgrade -y安裝依賴工具 sudo apt install -y ap…

大模型中提到的超參數是什么

在大模型中提到的超參數是指在模型訓練之前需要手動設置的參數&#xff0c;這些參數決定了模型的訓練過程和最終性能。超參數與模型內部通過訓練獲得的參數&#xff08;如權重和偏置&#xff09;不同&#xff0c;它們通常不會通過訓練自動學習&#xff0c;而是需要開發者根據任…

位運算及常用技巧

涉及位運算的運算符如下表所示&#xff1a; 位運算的運算律&#xff1a; 負數的位運算 首先&#xff0c;我們要知道&#xff0c;在計算機中&#xff0c;運算是使用的二進制補碼&#xff0c;而正數的補碼是它本身&#xff0c;負數的補碼則是符號位不變&#xff0c;其余按位取反…

組合總和III(力扣216)

這道題在回溯的基礎上加入了剪枝操作。回溯方面我就不過多贅述&#xff0c;與組合(力扣77)-CSDN博客 大差不差&#xff0c;主要講解一下剪枝(下面的代碼也有回溯操作的詳細注釋)。我們可以發現&#xff0c;如果我們遞歸到后面&#xff0c;可能集合過小&#xff0c;無法滿足題目…