再談C語言指針—指向另一指針的指針

一、回顧指針概念

早在本書第貳篇中我就對指針的實質進行了闡述。今天我們又要學習一個叫做“指向另一指針地址”的指針。讓我們先回顧一下指針的概念吧!
當我們程序如下聲明變量:
? ?short int i;
? ?char a;
? ?short int * pi;
程序會在內存某地址空間上為各變量開辟空間,如下圖所示:
圖中所示中可看出:
? ?i 變量在內存地址5的位置,占2個字節。
? ?a變量在內存地址7的位置,占1個字節。
? ?pi變量在內存地址9的位置,占2個字節。(注:pi 是指針,我這里指針的寬度只有2個字節,32位系統是4個字節)
接下來如下賦值:
? ?i = 50;
? ?pi = &i;
經過上在兩句的賦值,變量的內存映象如下:
看到沒有:短整型指針變量pi的值為5,它就是i變量的內存起始地址。所以,這時當我們對*pi進行讀寫操作時,其實就是對i變量的讀寫操作。如:
? ?*pi=5; /* 就是等價于i = 5; */
你可以回看本書的第貳篇,那里有更加詳細的解說。

二、指針的地址與指向另一指針地址的指針

在上一節中,我們看到,指針變量本身與其它變量一樣也是在某個內存地址中的,如pi的內存起始地址是9。同樣的,我們也可能讓某個指針指向這個地址。看下面代碼:
? ?short int **ppi; /* 這是一個指向指針的指針,注意有兩個“*”號 */
? ?*ppi = π
第一句:short int **ppi; —— 聲明了一個指針變量ppi,這個ppi是用來存儲(或稱指向)一個short int * 類型指針變量的地址。
第二句:&pi那就是取pi的地址,**ppi = &pi就是把pi的地址賦給了ppi。即將地址值9賦值給ppi。如下圖:
從圖中看出,指針變量ppi的內容就是指針變量pi的起始地址。于是……
? ?ppi的值是多少呢?—— 9。
? ?*ppi的值是多少呢?—— 5,即pi的值。
? ?**ppi的值是多少呢?——50,即i的值,也是*pi的值。
呵呵!不用我說太多了,我相信你應明白這種指針了吧!

三、一個應用實例

(1)設計一個函數:void find1(char array[], char search, char *pa)
要求:這個函數參數中的數組array是以0值為結束的字符串,要求在字符串array中查找字符是參數search里的字符。如果找到,函數通過第三個參數(pa)返回值為array字符串中第一個找到的字符的地址。如果沒找到,則為pa為0。

設計:依題意,實現代碼如下。
void find1(char array[], char search, char *pa)
{
? ?int i;
? ?for (i = 0; *(array + i) != 0; i++)
? ?{
? ? ? if ( *(array+i) == search)
? ? ? {
? ? ? ? ?pa = array + i;
? ? ? ? ?break;
? ? ? }
? ? ? else if (*(array+i) == 0)
? ? ? {
? ? ? ? ?pa = 0;
? ? ? ? ?break;
? ? ? }
? ?}
}
你覺得這個函數能實現所要求的功能嗎?

調試:我下面調用這個函數試試。
main()
{
? ?char str[] = {"afsdfsdfdf\0"}; /* 待查找的字符串 */
? ?char a = ’d’; /* 設置要查找的字符 */
? ?char *p = 0; /* 如果查找到后指針p將指向字符串中查找到的第1個字符的地址。 */
? ?find1(str, a, p); /* 調用函數以實現所要操作。 */
? ?if (0 == p)
? ?{
? ? ? printf("沒找到!\n"); /* 如果沒找到則輸出此句 */
? ?}
? ?else
? ?{
? ? ? printf("找到了,p = %d", p); /* 如果找到則輸出此句 */
? ?}
? ?return(0);
}
分析:上面代碼,你認為會是輸出什么呢?運行試試。
唉!怎么輸出的是:沒有找到!而不是“找到了,……”。

明明a值為’d’,而str字符串的第四個字符是’d’,應該找得到呀!
再看函數定義處:void find1(char array[], char search, char *pa)
看調用處:find1(str, a, p);

依我在第伍篇的分析方法,函數調用時會對每一個參數進行一個隱含的賦值操作。整個調用如下:
array = str;
search = a;
pa = p; /* 請注意:以上三句是調用時隱含的動作。*/
int i;
for(i =0; *(array+i) != 0; i++)
{
? ?if (*(array+i) == search)
? ?{
? ? ? pa = array + i;
? ? ? break;
? ?}
? ?else if (*(array+i)==0)
? ?{
? ? ? pa=0;
? ? ? break;
? ?}
}
哦!參數pa與參數search的傳遞并沒有什么不同,都是值傳遞嘛(小語:地址傳遞其實就是地址值傳遞嘛)!所以對形參變量pa值(當然值是一個地址值)的修改并不會改變實參變量p值,因此p的值并沒有改變(即p的指向并沒有被改變)。(如果還有疑問,再看一看《第五篇:函數參數的傳遞》了。)

修正:
void find2(char array[], char search, char **ppa)
{
? ?int i;
? ?for (i=0; *(array + i) != 0; i++)
? ?{
? ? ? if(*(array + i) == search)
? ? ? {
? ? ? ? ?*ppa = array + i;
? ? ? ? ?break;
? ? ? }
? ? ? else if(*(array + i) == 0)
? ? ? {
? ? ? ? ?*ppa = 0;
? ? ? ? ?break;
? ? ? }
? ?}
}
主函數的調用處改如下:
? ?find2(str, a, &p); /*調用函數以實現所要操作。*/
再分析:這樣調用函數時的整個操作變成如下:
array = str;
search = a;
ppa = &p; /* 請注意:以上三句是調用時隱含的動作。 */
int i;
for (i = 0; *(array + i) != 0; i++)
{
? ?if (*(array + i) == search)
? ?{
? ? ? *ppa = array + i
? ? ? break;
? ?}
? ?else if (*(array+i)==0)
? ?{
? ? ? *ppa=0;
? ? ? break;
? ?}
}
看明白了嗎?ppa指向指針p的地址。對*ppa的修改就是對p值的修改。你自行去調試。

經過修改后的程序就可以完成所要的功能了。看懂了這個例子,也就達到了本篇所要求的目的。

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

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

相關文章

Java練習 SDUT-1586_計算組合數

計算組合數 Time Limit: 1000 ms Memory Limit: 32768 KiB Problem Description 計算組合數。C(n,m),表示從n個數中選擇m個的組合數。 計算公式如下: 若:m0,C(n,m)1 否則, 若 n1,C(n,m)1 否則,若mn&#xf…

mysql日期時間操作函數詳解

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 win7可以設定每周從哪一天開始,win2003等不能方便的修改。有的是周日開始,有的是周一開始。而工作中有的時候每周…

對C語言進行調試的最好方法是什么?

要了解調試程序的最好方法,首先要分析一下調試過程的三個要素:應該用什么工具調試一個程序?用什么辦法才能找出程序中的錯誤?怎樣才能從一開始就避免錯誤?應該用什么工具調試一個程序?有經驗的程序員會使用許多工具來幫助調試程序,包括一…

如何賦值hook定義的變量

1、定義變量 const { tableProps, mutate} useRequest(async (params {}) > {const { success, data, total } await Api.getUserAccountApi({page: params.current || 1,...searchValue,});return {list: success ? data : [],total: success ? total : 0,};},{pagin…

java中的sleep()和wait()的區別

對于sleep()方法,我們首先要知道該方法是屬于Thread類中的。而wait()方法,則是屬于Object類中的。sleep()方法導致了程序暫停執行指定的時間,讓出cpu該其他線程,但是他的監控狀態依然保持者,當指定的時間到了又會自動恢…

Webpack4干貨分享(二),使用loader處理scss,圖片以及轉換JS

轉載請注明出處: 葡萄城官網 ,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。 原文出處: https://wanago.io/2018/07/16/webpack-4-course-part-two-webpack-4-course-part-two-loaders/今天繼續我們的Webpack 4…

spring-data-jpa 介紹 復雜查詢,包括多表關聯,分頁,排序

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 本篇進行Spring-data-jpa的介紹,幾乎涵蓋該框架的所有方面,在日常的開發當中,基本上能滿足所有需求。…

重寫laravel的request的校驗器

protected function failedValidation(Validator $validator) {$error $validator->errors()->all();throw new HttpResponseException(response()->json([data>[],code>500,msg>$error[0]], 500)); }

如何檢測C語言中的內存漏洞(leak)?

在動態分配的內存單元(即由函數malloc()或ealloc()分配的內存單元)不再使用卻沒有被釋放的情況下,會出現內存漏洞。未釋放內存單元本身并不是一種錯誤,編譯程序不會因此報告出錯,程序也不會因此而立即崩潰。但是,如果不再使用而又…

Oracle中row_number()、rank()、dense_rank() 的區別

link:https://www.cnblogs.com/qiuting/p/7880500.html轉載于:https://www.cnblogs.com/Spring-Rain/p/9716213.html

Vim使用教程(按鍵教程,映射都可以改的,持續更新)

修改映射 tnvim .vimrc 1、spaceft 調出目錄 2、controlh 跳到目錄 3、controll 跳到內容頁 4、spacekn 運行最近一個測試 5、spacekf 運行整個測試文件 6、spacekl 運行最后一個測試 7、sv 分屏 8、sq 退出分屏 9、controlp 搜索功能 10、/搜索內容 N向上…

Alpha 沖刺五

團隊成員 051601135 岳冠宇051604103 陳思孝031602629 劉意晗031602248 鄭智文031602234 王淇會議照片 項目燃盡圖 項目進展 暫無實質性進展。 項目描述 問題困擾: 商品分類出現困惑。交互部分向服務器發送請求失敗,安卓在4.0后對網絡請求有限制要求&…

什么是換碼符(escape character)?

換碼符是用來執行一個命令或一項任務的字符,它們不會被打印到屏幕上。例如,一個換碼符可以是這樣一個字符,它被傳遞給一個設備,告訴計算機屏幕以紅色而不是通常的白色來顯示下一行。這個換碼符將和真正要被設備以紅色來顯示的字符…

java日期工具類DateUtil

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 DateUtil類 [java] view plain copy package com.util; import java.text.SimpleDateFormat; import java.util.ArrayList; import…

Command 傳參的幾種方式

Command可以根據CommandParameter傳參 關鍵代碼 public ICommand SubmitCommand > _submitCommand; private RelayCommand _submitCommand new RelayCommand(new Action<object>(ShowMessage)); private static void ShowMessage(object obj) {MessageBox.Show(obj.T…

phpStorm重構快捷鍵(mac系統、持續更新)

參考 https://learnku.com/laravel/t/5420/your-keyboard-shortcuts-please 1、ctrlaltf 將表達式提取出來使其成為類的屬性&#xff0c;并自動更新引用。 2、ctrlaltp 將表達式變成由參數傳入 3、crtlF6 修改函數簽名&#xff08;函數名&#xff0c;函數參數&#xff09…

python -m xxx.py和python xxx.py的區別

先看下python -m site作用是顯示sys.path的值內容&#xff0c;也就是python搜索模塊的目錄&#xff0c;作用類似于linux下的PATH python -m SimpleHTTPServer 會在sys.path的所有路徑下查找SimpleHTTPServer.py文件&#xff1b; 而python SimpleHTTPServer.py則是在當前查找文…

C語言多維數組與多級指針

多維數組與多級指針也是初學者感覺迷糊的一個地方。超過二維的數組和超過二級的指針其實并不多用。如果能弄明白二維數組與二級指針&#xff0c;那二維以上的也不是什么問題了。所以本節重點討論二維數組與二級指針。一、二維數組 1、假想中的二維數組布局我們前面討論過&…

spring-data-jpa 使用

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 只是記錄下使用方法 &#xff1a; 1. RPC接口 service實現類調用&#xff0c;PageRequest對象會實現分頁、排序。 Overridepublic Obj…

docker的安裝與安裝mysql(mac,centos為例)

一、mac安裝docker 1、去這個網站下載安裝https://www.docker.com/get-started 2、運行docker 運行開啟docker docker run -dp 80:80 docker/getting-started 二、centos8安裝docker 1、安裝docker 下載低版本的 yum install -y docker-ce --nobest 2、安裝擴展 wget http…