【C語言】指針(二)

目錄

一、傳值調用和傳址調用

二、數組名的理解

三、通過指針訪問數組

四、一維數組傳參的本質

五、指針數組

六、指針數組模擬實現二維數組


一、傳值調用和傳址調用

指針可以用在哪里呢?我們看下面一段代碼:

#include <stdio.h>void Swap(int x, int y)
{int z = x;x = y;y = z;
}
int main()
{int a = 10;int b = 20;printf("交換前:a=%d b=%d\n", a, b);Swap(a, b);printf("交換后:a=%d b=%d\n", a, b);return 0;
}

運行結果如下:

我們發現,并沒有完成交換,調試發現:

出現這樣的原因:a和b是實參(是真實傳遞給函數的),x和y是形參,當實參ab傳給形參xy時候,形參把實參數據臨時拷貝了一份,x,y創建自己的獨立空間,因為有自己獨立的空間,跟a,b無關,所以修改形參不會影響實參。這種交換方式也叫傳值調用。

所以說:實參傳遞給形參的時候,形參會單獨創建?份臨時空間來接收實參,對形參的修改不影響實參。

措施:可以將a,b的地址傳給Swap函數,Swap函數里通過地址間接的操作main函數中的a和b,達到交換的效果。也就是傳址調用。

代碼如下:

#include <stdio.h>void Swap(int* pa, int* pb)//用指針變量來接收
{int z = *pa;*pa = *pb;*pb = z;
}
int main()
{int a = 10;int b = 20;printf("交換前:a=%d b=%d\n", a, b);Swap(&a, &b);//傳地址printf("交換后:a=%d b=%d\n", a, b);return 0;
}

傳址調用,可以讓函數和主調函數之間建立真正的聯系,在函數內部可以修改主調函數中的變量。

  • 未來函數中只是需要主調函數中的變量值來實現計算,就可以采用傳值調用。
  • 如果函數內部要修改主調函數中的變量的值,就需要傳址調用。

二、數組名的理解

數組名就是數組首元素(第一個元素)的地址。

代碼如下:

但有兩個例外:

  1. sizeof(數組名),sizeof中單獨放數組名,這里的數組名表示整個數組,計算的是整個數組的大小,單位是字節。
  2. &數組名,這里的數組名表示整個數組,所以&數組名取出的是整個數組的地址

除此之外,任何地方使用數組名,數組名都表示首元素的地址。

可能會有疑問,為什么首元素地址(arr)跟整個數組地址(&arr)相同呢?

代碼如下:

從值的角度來講,地址就是一個編號,它們打印出來的地址一模一樣,但是意義卻不相同,操作arr和&arr帶來的結果也是不一樣的。

如下代碼:

可以看出,&arr[0]和&arr[0]+1相差4個字節,arr和arr+1相差4個字節,是因為&arr[0]和arr都是首元素的地址,類型是int*,+1就是跳過一個整型(元素)。
但是&arr和&arr+1相差40個字節,這就是因為&arr是數組的地址,+1操作是跳過整個數組的。

也可以這么理解:

arr與&arr都是指針,指針有兩個要素:

  • 第一個是地址值,也就指向的位置,打印出來的就是地址值,arr與&arr的地址值是一樣的。
  • 第二個是類型(所指向的數據類型),arr指向數組第一個元素,&arr指向數組arr,arr+1后的地址值會偏移一個元素的長度,&arr+1后的地址值會偏移一整個數組的長度,所以arr與&arr類型是不一樣的。

三、通過指針訪問數組

#include <stdio.h>
int main()
{int arr[10] = { 0 };int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);int* p = arr;//p存放的數組首元素的地址for (i = 0; i < sz; i++){scanf("%d", p + i);//scanf("%d", arr+i);//也可以這樣寫}//輸出for (i = 0; i < sz; i++){printf("%d ", *(p + i));//輸出可以寫成:// *(p+i) <==> arr[i] <==> *(arr+i) <==> *(i+arr) <==> i[arr]}return 0;
}

可以發現,數組的下標引用操作符([ ])效果相當于解引用操作符(*)

其實數組元素的訪問在編譯器處理的時候,也是轉換成首元素的地址+偏移量求出元素的地址,然后解引用來訪問的。

四、一維數組傳參的本質

之前我們都是在函數外部計算數組的元素個數,那可以把函數傳給一個函數后,在函數內部求數組的元素個數嗎?

我們來看一段代碼:

#include <stdio.h>void test(int arr[])
{int sz2 = sizeof(arr) / sizeof(arr[0]);printf("sz2 = %d\n", sz2);
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int sz1 = sizeof(arr) / sizeof(arr[0]);printf("sz1 = %d\n", sz1);test(arr);return 0;
}

運行結果如下:

發現sz1計算錯誤,函數內部沒有正確獲得數組的元素個數。

原因:

數組名是數組首元素地址,傳遞的數組名,本質上數組傳參傳遞的是數組首元素地址。

所以函數的形參部分理論上應該用指針來接收首元素的地址。那么在函數內部寫sizeof(arr)計算的是一個地址的大小(單位字節),而不是數組的大小(單位字節)。

正因為函數的參數部分本質是指針,所以在函數內部是沒辦法求數組元素個數的。

代碼如下:

void test(int arr[10]) //==>arr[]  參數寫成數組形式,本質上還是指針
{
printf("%d\n", sizeof(arr)); //計算?個指針變量的??
}void test(int* arr) //參數寫成指針形式
{
printf("%d\n", sizeof(arr));
}
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
test(arr);
return 0;
}

上面數組傳參的本質是傳遞了數組首元素的地址,所以形參訪問的數組和實參的數組是同一個數組。

形參的數組是不會單獨再創建數組空間的,所以形參的數組是可以省略掉數組大小的。

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

五、指針數組

數組是一組相同類型元素的集合。數組有整形數組,字符數組.....

指針數組:存放指針(地址)的數組。

int* arr1[6];//存放整型指針的數組
char* arr2[10];//存放字符指針的數組

如下圖:

指針數組的每個元素是地址,又可以指向一塊區域。

六、指針數組模擬實現二維數組

代碼如下:

#include <stdio.h>
int main()
{int arr1[] = { 1,2,3,4,5 };int arr2[] = { 2,3,4,5,6 };int arr3[] = { 3,4,5,6,7 };//數組名是數組首元素的地址,類型是int*的,可以存放在parr數組中int* parr[3] = { arr1, arr2, arr3 };int i = 0;int j = 0;for (i = 0; i < 3; i++){for (j = 0; j < 5; j++){printf("%d ", parr[i][j]);//parr[i][j]<==>*(parr[i]+j)<==>*(*(parr+i)+j)}printf("\n");}return 0;
}

parr[i]是訪問parr數組的元素,parr[i]找到的數組元素指向了整型一維數組,parr[i][j]就是整型一維數組中的元素。

上述的代碼模擬出二維數組的效果,本質上其實不是二維數組。

因為二維數組在內存中是連續存放的,而這三個數組在內存可不一定連續存放。

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

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

相關文章

基于Spring封裝一個websocket工具類使用事件發布進行解耦和管理

最近工作中&#xff0c;需要將原先的Http請求換成WebSocket&#xff0c;故此需要使用到WebSocket與前端交互。故此這邊需要研究一下WebSocket到底有何優點和不可替代性&#xff1a; WebSocket優點&#xff1a; WebSocket 協議提供了一種在客戶端和服務器之間進行全雙工通信的…

如何在MATALB中調用libMR

? 因為個人項目原因,我曾將參考OpenMax源碼GitHub - abhijitbendale/OSDN: Code and data for the research paper “Towards Open Set Deep Networks” A Bendale, T Boult, CVPR 2016將其轉換到MATLAB使用。 OpenMax 使用極值理論實現對開放集的篩選,在計算得分時需要用l…

異地組網群暉不能訪問怎么辦?

在日常使用群暉網絡儲存設備時&#xff0c;我們常常會遇到無法訪問的情況&#xff0c;特別是在異地組網時。這個問題很常見&#xff0c;但也很讓人困擾。本文將針對異地組網群暉無法訪問的問題進行詳細解答和分析。 異地組網的問題 在異地組網中&#xff0c;群暉設備無法訪問的…

Unity | Spine動畫動態加載

一、準備工作 Spine插件及基本知識可查看這篇文章&#xff1a;Unity | Spine動畫記錄-CSDN博客 二、Spine資源動態加載 1.官方說明 官方文檔指出不建議這種操作。但spine-unity API允許在運行時從SkeletonDataAsset或甚至直接從三個導出的資產實例化SkeletonAnimation和Skel…

被耽誤了的發明家

高三的某一天&#xff0c;數學焦老師在黑板上推公式&#xff0c;突然花屁股&#xff08;見另一篇博文《數學老師們》&#xff09;上出現了一個光圈。我心里一樂&#xff0c;有人在玩鏡子。本來大家對于焦老師的花屁股已經司空見慣了&#xff0c;可以不受干擾地聽課&#xff0c;…

HNU-算法設計與分析-作業3

第三次作業【動態規劃】 文章目錄 第三次作業【動態規劃】<1>算法實現題 3-1 獨立任務最優解問題<2>算法實現題 3-4 數字三角形問題<3>算法實現題 3-8 最小m段和問題<4>算法實現題 3-25 m處理器問題 <1>算法實現題 3-1 獨立任務最優解問題 ▲問…

postgresql安裝及性能測試

postgresql安裝及性能測試 1. Postgresql介紹 Postgresql是一款功能強大的開源對象關系型數據庫管理系統&#xff08;ORDBMS&#xff09;&#xff0c;以其穩定性、擴展性和標準的SQL支持而聞名。它支持復雜查詢、外鍵、觸發器、視圖、事務完整性、多版本并發控制&#xff08;MV…

Linux(七) 動靜態庫

目錄 一、動靜態庫的概念 二、靜態庫的打包與使用 2.1 靜態庫的打包 2.2 靜態庫的使用 三、動態庫的打包與使用 3.1 動態庫的打包 3.2 動態庫的使用 3.3 運行動態庫的四種方法 四、總makefile 一、動靜態庫的概念 靜態庫&#xff1a; Linux下&#xff0c;以.a為后綴的…

Python專題:十五、JSON數據格式

Python的數據處理&#xff1a;JOSN 計算機的主要工作&#xff1a;處理數據 最容易處理的數據就是結構化數據 非結構化數據&#xff1a;視頻&#xff0c;文件等 近些年的大數據、數據挖掘就是對互聯網中的各種非結構化的數據的分析和處理 半結構化數據 明確的結構屬性&…

陪診服務運用預約小程序的效果是什么

在中高型城市里&#xff0c;陪診師近些年也很有熱度&#xff0c;已經衍生成為一個新的小眾行業&#xff0c;不同醫院/不同科目等其它情況針對不同群體往往很難完善&#xff0c;比如部分老年人腿腳不便、不認識字、外地語言難以溝通等&#xff0c;陪診師的作用就尤為凸顯. 對相…

[Bootloader][uboot]code總結

文章目錄 1、U_BOOT_DRIVER2、DM框架dm_scan_platdatadm_extended_scan_fdt 1、U_BOOT_DRIVER 使用這個宏可以定義一個驅動實例&#xff0c;宏定義是 其中使用的struct driver結構體 使用的ll_entry_declare宏定義是 歸結為 2、DM框架 1、 DM框架 DM模型抽象出了以下四個…

16.投影矩陣,最小二乘

文章目錄 1. 投影矩陣1.1 投影矩陣P1.2 投影向量 1. 投影矩陣 1.1 投影矩陣P 根據上節知識&#xff0c;我們知道當我們在解 A X b AXb AXb的時候&#xff0c;發現當向量b不在矩陣A的列空間的時候&#xff0c;我們希望的是通過投影&#xff0c;將向量b投影到矩陣A的列空間中&…

ModuleNotFoundError: No module named ‘sklearn‘

ModuleNotFoundError: No module named sklearn 解決辦法&#xff1a; pip install scikit-learn

7B2 PRO主題5.4.2免授權直接安裝

B2 PRO 5.4.2 最新免授權版不再需要改hosts&#xff0c;直接在wordpress上傳安裝即可

網站接入百度云防護CDN后回源率非常高原因

最近&#xff0c;有站長反饋網站接入百度云防護后&#xff0c;網站回源率非常高。 今天百度云來給大家講解下&#xff0c;CDN回源高的原因&#xff1a; 1.動態請求比較多 網站的動態請求很多&#xff0c;一般是回源率高的主要原因&#xff0c;因為CDN對待動態請求是每個請求…

Vue的學習 —— <網絡請求庫Axios>

目錄 前言 正文 一、Axios基本概念 二、安裝Axios 三、Axios使用方法 四、向服務器發送請求 前言 在之前的開發案例中&#xff0c;我們通常直接在組件中定義數據。但在實際的項目開發中&#xff0c;我們需要從服務器獲取數據。當其他用戶希望訪問我們自己編寫的網頁時&a…

定檔 11.2-3,COSCon'24 第九屆中國開源年會暨開源社十周年嘉年華正式啟動!

中國開源年會 COSCon 是業界最具影響力的開源盛會之一&#xff0c;由開源社在2015年首次發起&#xff0c;今年將舉辦第九屆。 以其獨特定位及日益增加的影響力&#xff0c;COSCon 吸引了越來越多的國內外企業、高校、開源組織/社區的大力支持。與一般企業、IT 媒體、行業協會舉…

網絡安全快速入門(十三)linux及vmware軟件的網絡配置

13.1 前言 在通過我們前面的了解&#xff0c;我們現在已經對Linux的基礎知識有了大致的了解&#xff0c;今天我們來大概講一下關于linux系統及vmware的網絡配置問題&#xff0c;在這之前&#xff0c;我們需要對網絡有一個大概的認識和了解&#xff0c;話不多說&#xff0c;我們…

01記-“計算機基礎知識”

感覺媒體: 直接作用于人的感覺器官&#xff0c;使人產生直接感覺的媒體&#xff1a;聲音、圖形、圖像、動畫等。 表示媒體: 為了加工、處理和傳輸感覺媒體而人為研究、構造出來的一種媒體&#xff0c;常見的有各種編碼方式&#xff0c;如文本編碼、圖像編碼和聲音編碼等。 …

Java中靜態方法為什么不能調用非靜態成員?

在Java面試中&#xff0c;這個問題經常被問到&#xff0c;因為它不僅涉及到Java的基本語法規則&#xff0c;還深入到了JVM的工作機制。理解這個問題可以幫助面試者更好地掌握Java的靜態和非靜態成員的區別以及它們在內存中的分配和使用。 靜態成員 vs 非靜態成員 首先&#x…