一篇文章了解指針變量

字符指針變量

在指針的類型中我們知道有一種指針叫做字符指針

它的使用情況如下:

#include<stdio.h>
int main()
{char pa = 'w';char*p1=&pa;*p1 = 'a';printf("%c\n", *p1);return 0;
}

在這段代碼當中,我們將‘w’字符的地址傳到了p1里面,而p1就是一個字符指針。

除了上面這種使用方法,還有一種關于字符指針變量的使用方法如下:

#include<stdio.h>
int main()
{char* p1 = "abced";printf("%s\n", p1);return 0;
}

有沒有感到很好奇,對于這段代碼的解釋,大家有什么想法嗎?

咱們的第一個反應應該是,這個是不是把字符串“abced”放到字符指針p1里面啊,但真實情況不是這樣的,這個是將“abced”中的首字母的地址放到了p1的指針變量當中,從而在打印的時候,可以通過p1找到字符串首字母的地址,從而順藤摸瓜地打印出整個字符串。

下面呢,我們來看一段代碼,這段代碼是一道經典的面試題,來自《劍指offer》

#include<stdio.h>
int main()
{char arr3[] = "hello,bit.";char arr4[] = "hello,bit.";char* p1 = "hello,bit.";char* p2 = "hello,bit.";if (arr3 == arr4){printf("arr3 and arr4 are the same\n");}elseprintf("arr3 and arr4 are not same\n");if (p1 == p2){printf("p1 and p2 are the same\n");}elseprintf("p1 and p2 are not same\n");return 0;
}

下面是這段代碼運行的結果

這個結果大家想到了嗎??

其中的原理如下:

在數組中,用相同的常量字符串初始化數組時,系統會開辟不同的內存空間。

而在指針當中,兩個指針指向的是同一個常量字符串,也就是指向同一個開辟下的內存空間。這個就是上面答案的原理所在。

數組指針變量

前面我們講了指針數組,指針數組是一個數組,存放的是指針(地址),而數組指針是一個指針,存放的是數組的地址,看下面兩個:

//指針數組和數組指針
//1.int*arr[10]
//?
//2.int(*arr)[10]

大家可以看看這兩個,哪個是指針數組,哪個是數組指針。

很明顯,第一個是指針數組,數組名是arr,數組中存放有10個元素,每個元素是int*類型

然后第二個是一個數組指針,根據優先級考慮,在這個當中,首先arr應該與*結合,構成一個指針,然后指向的是一個10個元素的數組,數組中的每個元素都是int類型

數組指針變量的初始化

數組指針是一個指針,存放的應該是數組的地址,那我們怎么可以得到數組的地址呢,&arr,通過這個便可以得到數組的地址

#include<stdio.h>
int main()
{int arr[10] = { 0 };int(*pte)[10] = &arr;return 0;
}

?

從這個當中我們可以看到,&arr和pte的地址是相同的,二者指向了同一塊內存空間,這個就是數組指針變量的初始化。

二維數組傳參的本質

有了前面的數組指針變量的基礎,我們就可以好好地了解一下二維數組傳參的內容,之前,我們寫過二維數組傳參的內容,請看下面的代碼:
?

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

?我們在之前的代碼當中,形參是數組形式,實參也是數組的形式,除了這個寫法,我們還有其他的寫法嗎?

我們再來看二維數組,二維數組其實可以看成是每個元素都是一維數組的數組,然后數組名是數組首元素的地址,也就是說,實參的第一個參數的意思是二維數組第一行的四個元素的地址,所以,我們可以在形參部分寫成這樣:

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

在這里,我們在詳細講一個*(*(ptr+i)+h),首先,先看最里面的那個括號,ptr是數組首元素的地址,ptr+i代表著二維數組的第幾行的地址,然后再加*找到第幾行的元素,也就是arr[i],然后用arr[i]+j代表的是第i行第j列的地址,然后在使用解引用符,就可以找到該地址所代表的元素,然后打印出來,就是數組。

數組名,是數組首元素的地址

&數組名,是數組的地址

函數名,是函數的地址

&函數名,也是函數的地址

二維數組傳參,形參可以形成數組形式,也可以寫成指針形式。

函數指針變量

通過前面對于指針變量的理解,我們大概可以知道,函數指針變量應該是一個指針變量,指向的應該是函數的地址,那么問題來了,函數有地址嗎?讓我們來看一下:

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

從上面的結果,我們可以看到,函數是有地址的,函數名就是函數的地址,那我們也可以通過&函數名來獲得函數的地址,那我們也可以通過函數地址的調用實現對于函數的調用。

如果我們將函數變量的地址存放起來,就可以創建函數指針了,函數指針其實和數組指針是極其相似的。

void test()
{printf("hehe");
}
void (*ptr1)() = test;
void(*ptr2)() = &test;int Add(int x, int y)
{return x + y;
}
int (*ptr3)(int, int) = Add;
int (*ptr4)(int x, int y) = &Add;//加不加 x,y都是可以的

?函數指針類型分析:

函數指針變量的使用

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

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

?

兩段有趣的代碼

接下來,我們來看兩段出自《C陷阱和缺陷》這本書中的代碼:

(*(void(*)())0)()?

//第一段:
//(*(void(*)())0)()
/*在這段代碼當中:
* 第一步:void(*)()這個是函數指針的類型
* 第二步:(void(*)())0----這個是對0的強制類型轉換,使0轉換成函數指針類型
* 第三步:(*(void(*)())0)()----是一個指針
*/

第二段:

第二段:
void (*signal(int, void(*)(int)))(int);
第一步:signal是一個函數名
第二步:函數名后面的(int, void(*)(int))是函數參數
第三步:整個又是一個函數指針,參數類型是int

typedef關鍵字

typedef是關鍵字沒在C語言當中可以起到重命名的作用

?

typedef int* unit;
typedef void(*ptr)(int);
typedef void(*deff)();

函數指針數組

我們之前學了指針數組,同理,函數指針數組是將函數指針放入數組當中,那么這個該怎么實現呢??

//函數指針數組
void (*)()ptr[10] =;?

?

?

?

?

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

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

相關文章

vue3 自己寫一個月的日歷

效果圖 代碼 <template><div class"monthPage"><div class"calendar" v-loading"loading"><!-- 星期 --><div class"weekBox"><div v-for"(item, index) in dayArr" :key"index&q…

2.修改列名與列的數據類型

修改字段名與字段數據類型 1.修改字段名 有時&#xff0c;在我們建好一張表后會突然發現&#xff0c;哎呀&#xff01;字段名貌似寫錯了&#xff01;怎么辦&#xff1f;要刪了表再重新建一個新表嗎&#xff1f;還是要刪了這個字段再新建一個新的字段&#xff1f; 都不用&…

AIGC專題報告:生成式人工智能人人可用的新時代

今天分享的AIGC系列深度研究報告&#xff1a;《AIGC專題報告&#xff1a;生成式人工智能人人可用的新時代》。 &#xff08;報告出品方&#xff1a;埃森哲&#xff09; 報告共計&#xff1a;21頁 人工智能發展迎來新拐點 ChatGPT 正在喚醒全球對人工智能&#xff08;AI&…

蛇形矩陣

蛇形矩陣是由1開始的自然數依次排列成的一個矩陣上三角形。 例如&#xff0c;當輸入5時&#xff0c;應該輸出的三角形為&#xff1a; 1 3 6 10 15 2 5 9 14 4 8 13 7 12 11 輸入描述&#xff1a;輸入正整數N&#xff08;N不大于100&#xff09; 輸出描述&#xff1a;輸出一個N…

MySQL七 | 存儲引擎

目錄 存儲引擎 存儲引擎特點 存儲引擎選擇 Innodb與MyISAM區別 存儲引擎 默認存儲引擎:InnoDB show engines;#展示當前數據庫支持的存儲引擎 存儲引擎特點 特點InnoDBMyISAMMemory存儲限制64TB有有事務安全支持--鎖機制行鎖表鎖表鎖Btree鎖支持支持 支持 Hash索引--支…

在pom.xml中添加maven依賴,但是類里面import導入的時候報錯

問題&#xff1a; Error:(27, 8) java: 類TestKuDo是公共的, 應在名為 TestKuDo.java 的文件中聲明 Error:(7, 23) java: 程序包org.apache.kudu不存在 Error:(8, 23) java: 程序包org.apache.kudu不存在 Error:(9, 23) java: 程序包org.apache.kudu不存在 Error:(10, 30) jav…

【場景測試用例】上傳文件

測試思路&#xff1a; 功能 上傳符合需求給的文件格式&#xff0c;大小&#xff0c;寬高等可以正常上傳 不同的文件格式最大/最小/中間的文件大小如支持批量上傳可以正常上傳 邊界值如支持刪除可以正常刪除指定文件&#xff0c;其他文件不受影響如支持預覽&#xff0c;可以正常…

【Java探索之旅】我與Java的初相識(一):Java的特性與優點及其發展史

&#x1f3a5; 嶼小夏 &#xff1a; 個人主頁 &#x1f525;個人專欄 &#xff1a; Java入門到精通 &#x1f304; 莫道桑榆晚&#xff0c;為霞尚滿天&#xff01; 文章目錄 一. Java語言概述與優勢1.1 Java的概述1.2 Java語言的優勢 二. Java領域與發展史2.1 Java的使用領域2.…

面試多線程八股文十問十答第二期

面試多線程八股文十問十答第二期 作者&#xff1a;程序員小白條&#xff0c;個人博客 相信看了本文后&#xff0c;對你的面試是有一定幫助的&#xff01; ?點贊?收藏?不迷路&#xff01;? 1.進程和線程的區別 概念不同&#xff1a;進程是操作系統中的一個獨立執行單元&a…

LeetCode56. Merge Intervals

文章目錄 一、題目二、題解 一、題目 Given an array of intervals where intervals[i] [starti, endi], merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input. Example 1: Input: interva…

目標檢測mAP計算以及coco評價標準

這篇是我對嗶哩嗶哩up主 霹靂吧啦Wz 的視頻的文字版學習筆記 感謝他對知識的分享 講一下目標檢測中的一些常見的指標 在我們使用目標檢測網絡訓練時 最后在驗證集上會得到一個coco的評價列表 就像我們圖中給的這一系列參數列表一樣 我們再進一步引入兩個概念 第一個叫做precisi…

P1 Qt的認識及環境配置

目錄 前言 01 下載Qt Creator windows下載安裝包拷貝到Linux Linux直接下載 02 Linux 安裝Qt 前言 &#x1f3ac; 個人主頁&#xff1a;ChenPi &#x1f43b;推薦專欄1: 《C_ChenPi的博客-CSDN博客》??? &#x1f525; 推薦專欄2: 《Linux C應用編程&#xff08;概念類…

地址欄不安全提示

在使用瀏覽器時訪問網站的時候&#xff0c;我們可能會遇到地址欄提示不安全的情況。這種情況通常都是是由于未安裝有效SSL證書或者網站SSL證書過期等原因導致的。本文將介紹如何處理地址欄提示不安全的問題&#xff0c;以確保我們的上網安全。 1&#xff0c;缺少SSL證書&#x…

golang游戲服務器 - tgf系列課程01

TGF框架的特點和功能 課程介紹了TGF框架的特點和功能在第一節課程中我們并不會介紹框架的使用。我們希望在這節課程中,能讓你了解到tgf是一個什么樣的框架 概要 本節課程介紹了TGF框架的特點和功能。TGF是一個開箱即用的服務器框架, 適合中小型團隊和獨立開發者進行游戲開發。…

基于單片機音樂盒仿真仿真系統設計

**單片機設計介紹&#xff0c;基于單片機音樂盒仿真仿真系統設計 文章目錄 一 概要二、功能設計設計思路 三、 軟件設計原理圖 五、 程序六、 文章目錄 一 概要 基于單片機的音樂盒仿真仿真系統是一種基于嵌入式系統技術的設計方案&#xff0c;用于模擬傳統的音樂盒功能。它通…

002 self-attention自注意力

目錄 一、環境 二、self-attention原理 三、完整代碼 一、環境 本文使用環境為&#xff1a; Windows10Python 3.9.17torch 1.13.1cu117torchvision 0.14.1cu117 二、self-attention原理 自注意力&#xff08;Self-Attention&#xff09;操作是基于 Transformer 的機器翻…

【XILINX】記錄ISE/Vivado使用過程中遇到的一些warning及解決方案

前言 XILINX/AMD是大家常用的FPGA&#xff0c;但是在使用其開發工具ISE/Vivado時免不了會遇到很多warning&#xff0c;(大家是不是發現程序越大warning越多&#xff1f;)&#xff0c;并且還有很多warning根據消除不了&#xff0c;看著特心煩&#xff1f; 我這里匯總一些我遇到的…

http和https區別

http和https區別 HTTP&#xff08;Hypertext Transfer Protocol&#xff09;和HTTPS&#xff08;Hypertext Transfer Protocol Secure&#xff09;是用于在網絡上傳輸數據的兩種協議。它們之間的主要區別在于安全性和數據傳輸方式&#xff1a; 安全性&#xff1a;HTTP是明文傳…

華清遠見嵌入式學習——QT——作業2

作業要求&#xff1a; 代碼運行效果圖&#xff1a; 登錄失敗 和 最小化 和 取消登錄 登錄成功 和 X號退出 代碼&#xff1a; ①&#xff1a;頭文件 #ifndef LOGIN_H #define LOGIN_H#include <QMainWindow> #include <QLineEdit> //行編輯器類 #include…

如何在centos8上配置一個ca證書頒發機構并且頒發一個自簽名證書【超詳細!!!】

在CentOS 8上配置CA證書頒發機構并頒發自簽名證書的步驟如下&#xff1a; 1. 安裝OpenSSL sudo dnf install openssl 2. 創建CA證書目錄 sudo mkdir /etc/pki/CA/ sudo chmod 0700 /etc/pki/CA/ 3. 創建CA證書數據庫 sudo touch /etc/pki/CA/index.txt sudo echo 1000 >…