#C語言——學習攻略:深挖指針路線(四)--字符指針變量,數組指針變量,二維數組傳參的本質,函數指針變量,函數指針數組

🌟菜鳥主頁:@晨非辰的主頁

👀學習專欄《C語言學習》

💪學習階段:C語言方向初學者

?名言欣賞:"暴力解法是上帝給的,優化解法是魔鬼教的。"


目錄

1. 字符指針變量

1.1 使用方式

1.2 例題解釋

2. 數組指針變量

2.1 數組指針變量定義????????

?2.2 數組指針變量的初始化

3. 二維數組傳參本質

4. 函數指針變量

4.1 函數指針變量的創建

4.2 函數指針變量的使用

4.3 有趣的代碼

4.3.1?typedef關鍵詞

5. 函數指針數組


1. 字符指針變量

1.1 使用方式

--已經知道有一種指針類型為字符指針:char*,一般有兩種使用方式:

int main()
{//第一種char ch = 'w';char* pc = &ch;//第二種char arr[] = "abcdef";char* pc = arr;return 0;
}

--當然還有另外方式:

int main()
{const char* pc = "abcdef";//這里代表把整個字符串放進了指針嘛?//結果顯而易見,字符串為常量字符串,只是將首字符的地址存放printf("%c\n", *pc);//打印aprintf("%s\n", pc);//打印abcdef//%s打印字符串需要的是地址才能找到下一個字符,所以用pcreturn 0;
}

--對于方式3和方式2對比,方式3略過了數組,這就導致了無法通過*pc來改變字符串,也就是上面說的常量字符串。

1.2 例題解釋

--經典筆試題:

int main()
{char str1[] = "hello bit.";char str2[] = "hello bit.";const char* str3 = "hello bit.";const char* str4 = "hello bit.";if (str1 == str2)printf("str1 and str2 are same\n");//1elseprintf("str1 and str2 are not same\n")//2;if (str3 == str4)printf("str3 and str4 are same\n");//3elseprintf("str3 and str4 are not same\n");//4return 0;
}

--代碼打印;2、3;

????????--首先請注意,根據博客指針(三)的內容,這里比較的都是數組首元素地址而不是數組內容;所以因為str1與str2雖然內容相同但為不同數組,首元素地址自然也不同;

? ? ? ? --對于str3與str4,都指向同一個字符串"abcdef"且為常量字符串,內容不會被修改,C/C++會把常量字符串存儲到單獨的一個內存區域,當幾個指針指向同一個字符串時,他們實際會指向同一塊內存,所以str3和str4相同。

--特別注意,比較字符串內容要使用strcmp函數


2. 數組指針變量

2.1 數組指針變量定義????????

--在上一篇博客,學習了指針數組,數組存放的是指針;那下面也進行類比:

  • 整型指針變量:int* p,存放的整型變量地址,指向整型數據;
  • 字符指針變量;char* p,存放的字符型變量地址(字符串,存放的是首字符地址),指向字符型數據

--可知,數組指針存放的是數組地址,指向數組數據;

--下面對數據指針變量進行辨析:

1. int* p1[10]; --首先p1與[10]結合,那么p1就成了數組名,這也就是前面學的指針數組

2. int(*p2)[10]; --首先p2與*結合,p2成為指針變量名,[10]代表指針所指向的是大小為10的數組;所以是數組指針(必須確保加上(),使p先于和*結合)

?2.2 數組指針變量的初始化

--數組指針變量用來存放數組地址,那么初始化就要獲取數組地址:&數組名。

int(*p) [10] = &arr; --&arr得到數組地址

--數組類型解釋:

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

? |? ? ? |? ? ? ? |

? |? ? ? |? ? ?p指向數組的元素個數

? |? ? p為指針變量名

p指向的數組的元素類型


3. 二維數組傳參本質

--認識了數組指針,下面來理解二維數組是如何傳參的吧:

//構建函數
void test(int arr[][5], int a, int b)
{int i = 0;int j = 0;for (i = 0; i < a; i++){for (j = 0; j < b; j++){printf("%d ", arr[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]。

--就意味著二維數組傳參本質上也是傳遞地址,傳遞的是第一行?維數組地址,那么形參也是可以寫成指針形式的:

void test(int(*arr) [5], int a, int b)
{int i = 0;int j = 0;for (i = 0; i < a; i++){for (j = 0; j < b; j++){printf("%d ", *(*(arr+i)+j));//*(arr + i) 解引用得到 arr[i](第 i 行的數組名)//+j再解引用是訪問一維數組的內容,等價于arr[][]}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;

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


4. 函數指針變量

4.1 函數指針變量的創建

--同樣類比其他指針,函數指針就是存放函數地址的,通過地址調用函數,那函數地址怎么獲取呢?

void test()
{printf("hehe\n");
}
int main()
{printf("test:  %p\n", test);printf("&test: %p\n", &test);return 0;
}

? ? ? ? --可見函數是有地址的,函數名就是地址(與數組不一樣)。

--下面就要開始創建變量來存放地址:


int* test(int n, char* p)
{(...);
}int* (*pf)(int, char*) = test;int Add(int x, int y)
{return x + y;
}//參數可寫可不寫
int(*pf)(int, int) = Add;

--函數指針類型圖解:

4.2 函數指針變量的使用

--通過函數指針調用指針指向的函數

int Add(int x, int y)
{return x + y;
}
int main()
{int(*pf)(int, int) = Add;printf("%d\n", (*pf)(10, 20));printf("%d\n", pf(10, 20));//解不解引用都可以,因為pf在這里等價于Addreturn 0;
}

--? 注意:C 語言標準規定,函數指針的解引用會自動轉換回函數地址,因此 *pf 仍然等同于 pf。

4.3 有趣的代碼

--代碼1

(* (void (*)())0)();

--解釋:這段代碼是在調用0地址處的函數

  1. ?void(*)()是一個函數指針類型,這個指針指向的函數沒有參數,返回類型void;
  2. ?(void (*)())0?是將0強轉為這種函數指針類型,意味著0處有這么一個函數;
  3. (* (void (*)())0)();對0地址進行解引用,調用函數;

--來自《C陷阱和缺陷》

?--代碼2

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

--解釋:是一次函數聲明,函數名叫signal

  1. signal函數有兩個參數,第一個參數是int類型,第二個參數是函數指針類型?void(*)(int),該指針指向的函數參數是int,返回類型是void;
  2. signal函數的返回類型也是一個函數指針類型?void(*)(int) ,指針指向的函數參數是int,返回類型是void;
  3. 直觀表達:void *?(int)?signal (int , void(*)(int)) ;//但是不能這么寫

--來自《C陷阱和缺陷》

4.3.1?typedef關鍵詞

--顯而易見,typedef用來類型重命名的,可以將復雜的類型簡單化。

?--比如:

unsigned int 太長不方便,可以用關鍵詞重定義為uint :typedef??unsigned?int??uint;

? ? ? ? ?--指針類型也可以簡化命名的,將int *重命名

typedef??int*? ptr_t;

? ? ? ? --但是對于數組指針和函數指針就有不同:

? ? ? ?--?數組指針類型?int (*) [5] ,需要重命名為parr_t,要這樣寫:

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

? ? ? ? --函數指針類型重命名是一樣的,將?void(*) (int)?類型重命名為pfun_t,可以這樣寫:

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

?--那么為了更好理解上面的代碼2,這樣命名:

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


5. 函數指針數組

--在上一篇博客分享了指針數組,那么把函數的地址放到數組中,就成為了函數指針數組,如何定義呢?

int (*parr1[3])();

?--parr1先和 [ ] 結合,說明parr1是數組,內容是 int (*)()類型的指針;

--對于函數指針的用途:轉移表,小子會在下一篇進行分享,千萬別急~~?


往期復習:

1.?#C語言——學習攻略:深挖指針路線(一)--指針變量、地址、意義與指針運算

2.?#C語言——學習攻略:深挖指針路線(二)--const修飾、野指針分析、斷言和指針的作用

3.?#C語言——學習攻略:深挖指針路線(三)--數組與指針的結合、冒泡排序


結語:本篇內容就到這里了,主要分享了指針變量類型的一些內容,后續仍會分享指針的相關知識;指針的內容需要反復研讀 ,如果這篇文章對你的學習有幫助的話,歡迎一起討論學習,你這么帥、這么美給個三連吧~~~

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

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

相關文章

SpringBoot收尾+myBatis plus

一、數據傳遞返回值為:字符串package com.apesource.springboot_web_04.controller;import com.apesource.springboot_web_04.pojo.Emp; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping;/*** 返回值為:字符…

基于 Spring Boot 實現動態路由加載:從數據庫到前端菜單的完整方案

在后臺管理系統中&#xff0c;不同用戶角色往往擁有不同的操作權限&#xff0c;對應的菜單展示也需動態調整。動態路由加載正是解決這一問題的核心方案 —— 根據登錄用戶的權限&#xff0c;從數據庫查詢其可訪問的菜單&#xff0c;封裝成前端所需的路由結構并返回。本文將詳細…

VitePress學習-自定義主題

VitePress-自定義主題 代碼倉庫 基礎了解 初始化項目的時候選擇 custom theme 運行后會發現頁面挺丑的。 如果想要用默認主題怎么辦呢&#xff0c;修改Layout。 使用默認主題的Layout <script setup lang"ts"> import { useData } from vitepress; impo…

【GEO從入門到精通】生成式引擎與其他 AI 技術的關系

2.1.3 生成式引擎與其他 AI 技術的關系生成式引擎作為人工智能領域的創新力量&#xff0c;與其他 AI 技術緊密相連&#xff0c;相互促進&#xff0c;共同推動 生成式引擎優化&#xff08;GEO&#xff09; 的發展。這些技術使生成式引擎能夠為消費者提供更加個性化和精準的內容。…

JAVAEE--4.多線程案例

設計模式1.單例模式1.1餓漢模式1.2懶漢模式(單線程版)1.3懶漢模式(多線程版本)1.4懶漢模式(多線程版本進階版)2.阻塞隊列3.定時器4.線程池1.單例模式設計模式是"軟性約束",不是強制的,可以遵守也可以不遵守,按照設計模式寫代碼使代碼不會太差框架是"硬性約束&qu…

量化感知訓練(QAT)流程

WHAT&#xff1a;量化感知訓練&#xff08;Quantization-Aware Training, QAT&#xff09; 是一種在模型訓練階段引入量化誤差的技術。它的核心思想是&#xff1a;通過在前向傳播時插入“偽量化節點”引入量化誤差&#xff0c;將權重和激活模擬為低精度&#xff08;如 int8&…

docker 用于將鏡像打包為 tar 文件

docker save 是 Docker 中用于將鏡像打包為 tar 文件的命令&#xff0c;常用于鏡像的備份、遷移或離線傳輸。以下是其核心用法和注意事項&#xff1a;一、基本語法bashdocker save [選項] IMAGE [IMAGE...] > 文件名.tar # 或 docker save -o 文件名.tar IMAGE [IMAGE...]IM…

設計模式(六)創建型:單例模式詳解

設計模式&#xff08;六&#xff09;創建型&#xff1a;單例模式詳解單例模式&#xff08;Singleton Pattern&#xff09;是 GoF 23 種設計模式中最簡單卻最常被誤用的創建型模式。其核心價值在于確保一個類在整個應用程序生命周期中僅存在一個實例&#xff0c;并提供一個全局訪…

PostgreSQL AND OR 操作符詳解

PostgreSQL AND & OR 操作符詳解 在數據庫查詢中,AND 和 OR 是兩種常見的邏輯操作符,用于組合多個查詢條件。PostgreSQL 作為一款功能強大的開源關系型數據庫管理系統,同樣支持這些操作符。本文將詳細介紹 PostgreSQL 中的 AND 和 OR 操作符,并探討它們在查詢中的應用…

RabbiteMQ安裝-ubuntu

Ubuntu 1.安裝Erlang RabbitMQ需要Erlang語言的支持&#xff0c;在安裝RabbitMQ之前需要安裝Erlang #更新軟件包 sudo apt-get update#安裝erlang sudo apt-get install erlang查看erlang版本 roothcss-ecs-027f:/# erl Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [sm…

Linux驅動20 --- FFMPEG視頻API

目錄 一、FFMPEG 視頻 API 的使用 1.1 介紹 1.2 整體編程過程 獲取核心上下文指針 打開輸入流文件 獲取輸入流 獲取編碼器 初始化解碼器 申請輸出流指針 獲取顯示數據空間大小 申請輸出顯示空間 綁定輸出流和輸出顯示空間 申請格式轉換上下文 申請輸入流指針 讀取一幀數據 發…

OpenBayes 一周速覽丨Self Forcing 實現亞秒級延遲實時流視頻生成;邊緣AI新秀,LFM2-1.2B采用創新性架構超越傳統模型

公共資源速遞 This Weekly Snapshots &#xff01; 5 個公共數據集&#xff1a; * AF-Chat 音頻對話文本數據集 * ArtVIP 機器交互式圖像數據集 * Updesh 印度語合成文本數據集 * Medical Information 藥品信息數據集 * Nemotron-Math-HumanReasoning 數學推理數據集…

[NOIP2002 提高組] 均分紙牌

題目描述有N堆紙牌&#xff0c;編號分別為 1,2,…,N。每堆上有若干張&#xff0c;但紙牌總數必為N的倍數。可以在任一堆上取若干張紙牌&#xff0c;然后移動。移牌規則為&#xff1a;在編號為1堆上取的紙牌&#xff0c;只能移到編號為2的堆上&#xff1b;在編號為N的堆上取的紙…

【音視頻】WebRTC-Web 音視頻采集與播放

一、打開攝像頭 打開攝像頭首先需要有一個html的video標簽&#xff1a; id "local-video"&#xff0c;是為了后續的js腳本調用這個對象autoplay是設置打開后自動播放&#xff0c;playsinline則是為了兼容移動端 <video id "local-video" autoplay p…

數據治理平臺如何選?深度解析國產化全棧方案與行業落地實踐

“數據治理平臺廠商有哪些&#xff1f;”國內主流廠商包括阿里云、華為、百分點科技等&#xff0c;各有所長。其中&#xff0c;百分點科技憑借在應急管理、智慧公安及央國企數字化領域的深度實踐&#xff0c;打造了行業特色鮮明的數據治理解決方案。百分點科技的數據治理解決方…

限流算法詳解:固定窗口、滑動窗口、令牌桶與漏桶算法全面對比

限流&#xff08;Rate Limiting&#xff09;是保障系統穩定性和服務質量的關鍵機制&#xff0c;尤其在高并發、突發流量、攻擊防護等場景中至關重要。本文將詳細介紹四種主流限流算法&#xff1a;固定窗口&#xff08;Fixed Window&#xff09;滑動窗口&#xff08;Sliding Win…

Sentinel 搭建應用層面與網關層面的流控保護

源碼&#xff1a;妖精的尾巴/spring-cloud-alibaba Nacos 和 Sentinel Dashboard 我這里全是使用window 本地運行的&#xff0c;需要自行下載運行 服務層面&#xff1a; 當你在某個具體的服務上使用Sentinel時&#xff0c;更多的是關注該服務內部資源的保護。例如&#xff0c…

純血鴻蒙 AudioRenderer+AudioCapturer+RingBuffer 實現麥克風采集+發聲

總共兩個類&#xff0c;放到代碼里&#xff0c;就可以快速完成K歌的效果&#xff0c;但應用層這么做延遲是比較高的&#xff0c;只是做一個分享。 類代碼 import { audio } from kit.AudioKit; import { BusinessError } from kit.BasicServicesKit; import { AudioBufferFlow,…

洛谷 P1601 A+B Problem(高精)普及-

題目描述 高精度加法&#xff0c;相當于 ab problem&#xff0c;不用考慮負數。 輸入格式 分兩行輸入。a,b≤10500a,b \leq 10^{500}a,b≤10500。 輸出格式 輸出只有一行&#xff0c;代表 ababab 的值。 輸入輸出樣例 #1 輸入 #1 1 1輸出 #1 2輸入輸出樣例 #2 輸入 #2 1001 909…

Matrix Theory study notes[6]

文章目錄linear spacereferenceslinear space a basis of linear space VkV^kVk,which is x1,x2,...xkx_1,x_2,...x_kx1?,x2?,...xk?,can be called as a coordinate system.let vector v∈Vkv \in V^kv∈Vk and it can be linear expressed on this basis as va1x1a2x2...…