C 溫故知新 之 指針:數組指針、字符串指針、函數指針

一、數組指針? 1.指向數組元素的指針

  1、定義:還是那句話通俗的說指針就是地址  

    數組指針?????:數組的起始地址

    數組元素指針:數組元素的地址

  2、定義一個指向數組元素的指針變量的方法,與之前介紹的指針變量相同。

    例如:?
???      int a[10];?? /*定義 a 為包含10 個整型數據的數組*/
    ???? int *p;????? /*定義p為指向整型變量的指針*/

  3、指針變量賦值:
    p=&a[0]; //或者:p=a; 原因是p,a,&a[0]均指向同一單元

    把 a[0]元素的地址賦給指針變量 p。也就是說,p指向 a 數組的第 0 號元素。

  4、格式

    類型說明符? *指針變量名;

2. 通過指針引用數組元素

?

看圖識字:

  1、 p+i 和a+i 就是 a[i]的地址,或者說它們指向 a數組的第 i個元素。

  2、*(p+i)或*(a+i)就是p+i或a+i所指向的數組元素, 即a[i]。 例如, *(p+5)或*(a+5)就是a[5]。

  3、指向數組的指針變量也可以帶下標,如 p[i]與*(p+i)等價。

根據以上敘述,引用一個數組元素可以用:
  1、下標法,即用 a[i]形式訪問數組元素。
  2、指針法,即采用*(a+i)或*(p+i)形式,用間接訪問的方法來訪問數組元素,其中 a是數組名,p是指向數組的指針變量,其處值 p=a。

Eg:

  1、下標法:

  

?????????????????

?  2、通過數組名計算元素的地址

    

????????????????

?  3、指針變量指向元素

      

??????????? ??

  注意的問題

    1、指針變量可以實現本身的值的改變。如 p++是合法的;而 a++是錯誤的。因為 a 是數組名,它是數組的首地址,是常量。

    2、要注意指針變量的當前值。請看下面的程序。

?

int a[10],i,*p;p=a;//p=&a[0]for(i=0;i<10;i++)*p++=i; //a[i++]=ifor(i= 0;i<10;i++)printf("a[%d]=%d\n",i,*p++);

?

你看看出問題嗎?如果可以別忘了告訴我(雖然書上解釋了“要注意指針變量的當前值”但是還是有點迷糊)

看看運行結果

    

?????????

?

正確的方法就是把上面注釋的部分拿出來即可,看看結果:

  

???? ??

?

?

?

?

3.數組名作函數參數

?  數組名可以作函數的實參和形參

main() 
{int array[10]; …… …… f(array,10); 
…… …… 
} f(int arr[],int n); { 
…… …… 
} 
array 為實參數組名,arr為形參數組名。

?  Eg:將數組 a 中的 n 個整數按相反順序存放。

    1、形參是數組名

main()
{//將數組 a 中的 n 個整數按相反順序存放。 int i,a[10]={3,7,9,11,0,6,7,5,4,2};printf("The original array:\n");for(i=0;i<10;i++){printf("%d,",a[i]);}printf("\n");inv(a,10);printf("The array has been inverted:\n");for(i=0;i<10;i++){printf("%d,",a[i]);}printf("\n");
}
/*形參是數組名*/inv(int x[],int n)
{int temp,i,j,m=(n-1)/2;for(i=0;i<m;i++){j=n-1-i;temp=x[i];x[i]=x[j];x[j]=temp; } 
}

    2、形參x為指針變量

/*形參x為指針變量*/inv2(int *x,int n){int *p,temp,*i,*j,m=(n-1)/2;i=x ;j=x+n-1;p=x+m;for(;i<=p;i++,j--){temp=*i;*i=*j;*j=temp;}return;}

  歸納總結:如果有一個實參數組,想在函數中改變此數組的元素的值,實參與形參的對應關系有以下4種:

    1、形參和實參都是數組名。

      main()??????????????????? f(int x[],int n) {?……}
      {int a[10];?
?       ……?
?      f(a,10)?
?       ……
      }?

    2、實用數組,形參用指針變量

      main()???????????????????? ?f(int *x,int n) {??…… }
      {int a[10];
?       ……
      ?f(a,10)?
?       ……
      }

    3、 實參、型參都用指針變量

    4、實參為指針變量,型參為數組名

4.指向多維數組的指針和指針變量

?  1.? 多維數組的地址 設有整型二維數組 a[3][4]如下:
     0?? 1?? 2?? 3?
???   ?? 4?? 5?? 6?? 7
     8?? 9? 10? 11
  它的定義為:
    int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}}

?  C語言允許把一個二維數組分解為多個一維數組來處理,因此數組 a 可分解為三個一維數組,即 a[0],a[1],a[2]   

?? ?

  例如 a[0]數組,含有 a[0][0],a[0][1],a[0][2],a[0][3]四個元素。

  a[0]是第一個一維數組的數組名和首地址,因此a,a[0],*(a+0),*a,&a[0][0]是相等的。

  Eg:

  

    int a[3][4] ={0,1,2,3,4,5,6,7,8,9,10,11}; //0,1,2,3   a[0]行//4,5,6,7   a[1]行//8,9,10,11 a[2]行printf("0\n");printf("%d\n",*(a+0)); printf("%d\n",a); printf("%d\n",*a);  printf("%d\n",a[0]); printf("%d\n",&a[0]);  printf("%d\n",&a[0][0]); printf("………………………………………………\n");printf("1\n");printf("%d\n",a+1);  printf("%d\n",*(a+1));  printf("%d\n",a[1]);  printf("%d\n",&a[1]);  printf("%d\n",&a[1][0]); printf("………………………………………………\n"); printf("2\n");printf("%d\n",a+2);  printf("%d\n",*(a+2));  printf("%d\n",a[2]);  printf("%d\n",&a[2]);  printf("%d\n",&a[2][0]); printf("………………………………………………\n"); printf("3【a[1]行+1=>1244996+4】\n");printf("%d\n",a[1]+1);  printf("%d\n",*(a+1)+1); printf("………………………………………………\n"); printf("取2行值\n");printf("%d,%d\n",*(a[1]+0),*(*(a+1)+0)); printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1)); printf("%d,%d\n",*(a[1]+4),*(*(a+1)+4)); //越界繼續向下取值8*/

?

  結果:

   

?

  2.指向多維數組的指針變量
  把二維數組 a 分解為一維數組 a[0],a[1],a[2]之后,設 p 為指向二維數組的指針變量。可定義為:?
?????   int (*p)[4]
  它表示 p 是一個指針變量,它指向包含 4 個元素的一維數組。若指向第一個一維數組a[0],其值等于 a,a[0],或&a[0][0]等。而 p+i 則指向一維數組 a[i]。從前面的分析可得出*(p+i)+j是二維數組 i 行j 列的元素的地址,而*(*(p+i)+j)則是i行 j 列元素的值。

  二維數組指針變量說明的一般形式為:

    類型說明符? (*指針變量名)[長度]

  注意“(*指針變量名)”兩邊的括號不可少,如缺少括號則表示是指針數組

  eg:

main(){ int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11}; int(*p)[4]; int i,j; p=a; for(i=0;i<3;i++) {for(j=0;j<4;j++) printf("%2d  ",*(*(p+i)+j)); printf("\n");} 
} 

?

二、字符串指針 1、字符串的表示形式

?  C 語言中,可以用兩種方法訪問一個字符串:

    1、用字符數組存放一個字符串,然后輸出該字符串

    2、用字符串指針指向一個字符串

  

????????

?

?

?

?

?2、?使用字符串指針變量與字符數組的區別

  1、字符串指針變量本身是一個變量,用于存放字符串的首地址,而字符串本身是存放在以該首地址為首的一塊連續的內存空間中并以‘\0’作為串的結束

  2、對字符串指針方式 char *ps="C Language";

    可以寫為:?
???      char *ps;
      ps="C Language";
    而對數組方式:?
???     static char st[]={"C Language"};
    不能寫為:?
???     char st[20];?
???     st={"C Language"}; 而只能對字符數組的各元素逐個賦值。

?

?三、函數指針    

  ?在C語言中,一個函數總是占用一段連續的內存區,而函數名就是該函數所占內存區的首地址。我們可以把函數的這個首地址(或稱入口地址)賦予一個指針變量,使該指針變量指向該函數。然后通過指針變量就可以找到并調用這個函數。我們把這種指向函數的指針變量稱為“函數指針變量”。

   函數指針變量定義的一般形式為:

     類型說明符? (*指針變量名)();

  其中“類型說明符”表示被指函數的返回值的類型。 “(* 指針變量名)”表示“*”后面的變量是定義的指針變量。最后的空括號表示指針變量所指的是一個函數。

  例如:?
???   int (*pf)();

  Eg:

    

main()
{int comMax(int a,int b);int (*pmax) ();//定義:類型說明符  (*指針變量名)(); 表示 pmax 是一個指向函數入口的指針變量,該函數的返回值(函數值)是整型。int x,y,z;pmax=comMax;printf("input two numbers:\n");scanf("%d%d",&x,&y);z=(*pmax)(x,y);//調用函數的一般形式為:(*指針變量名) (實參表)  或者 comMax(x,y);printf("max=%d",z);  
}int comMax(int a,int b)
{if(a>b) return a; else return b;
}

  結果:

??????????

?

  從上述程序可以看出用,函數指針變量形式調用函數的步驟如下:?

    1、先定義函數指針變量,如后一程序中第 9 行 int (*pmax)();定義 pmax 為函數指針變量

    2、把被調函數的入口地址(函數名)賦予該函數指針變量,如程序中第 11 行 pmax=max;

    3、用函數指針變量形式調用函數,如程序第 14 行 z=(*pmax)(x,y);

    4、調用函數的一般形式為:
      ? ?(*指針變量名) (實參表)
      使用函數指針變量還應注意以下兩點:

        a、函數指針變量不能進行算術運算,這是與數組指針變量不同的。數組指針變量加減一個整數可使指針移動指向后面或前面的數組元素,而函數指針的移動是毫無意義的 ?

        b、函數調用中"(*指針變量名)"的兩邊的括號不可少,其中的*不應該理解為求值運算,在此處它只是一種表示符號


作者:PEPE
出處:http://pepe.cnblogs.com/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

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

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

相關文章

mysql 查找配置文件 my.ini 位置方法

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 個人備注&#xff1a;不顯示文件類型時&#xff0c;my.ini 文件名就叫作 my&#xff0c; 文件屬性才顯示 ini。 找到 my 文件看屬性就知…

嵌入式操作系統內核原理和開發

嵌入式操作系統內核原理和開發&#xff08;開篇&#xff09; 操作系統是很多人每天必須打交道的東西&#xff0c;因為在你打開電腦的一剎那&#xff0c;隨著bios自檢結束&#xff0c;你的windows系統已經開始運行了。如果問大家操作系統是什么&#xff1f;可能有的人會說操作…

Java中對象比較

在Java之中不僅僅存在兩個數字與兩個字符串之間的比較&#xff0c;還存在兩個對象之間的比較。 眾所周知&#xff0c;兩個數字之間的比較我們使用“”&#xff0c;兩個字符串之間的比較我們使用“equals()”&#xff0c;那么兩個對象之間如何進行比較呢&#xff1f;既然要進行兩…

如何安裝pfbprophet

最近facebook出來了一個軟件包&#xff0c;可以用于時序數據預測&#xff0c;但是安裝上&#xff0c;遇到問題不小&#xff0c;本人也在安裝中遇到大大小小各種問題&#xff0c;然后查了各種資料&#xff0c;進行研究&#xff0c;終于找到一個最簡單的辦法。 不廢話&#xff0…

JeeSite 4.0 (1.0)開發環境部署運行

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 環境要求 1、Java SDK 1.8 下載 2、Eclipse IDE for Java EE Mars 2 (4.5.2) 下載&#xff08;依Eclipse舉例&#xff0c;IDEA雷同。&…

dojo 七 DOM dojo/dom

官方教程&#xff1a;Dojo DOM Functions對dom的使用&#xff0c;需要引用包dojo/dom。1.獲取節點&#xff0c;dom.byIdbyId中既可以傳遞一個字符串&#xff0c;也可以傳遞一個節點對象 require(["dojo/dom", "dojo/domReady!"], function(dom) {function …

quantaxis中使用docker安裝,出現的問題

本人在使用docker安裝quantaxis時&#xff0c;經常發生docker報錯&#xff0c;原因是與 wsl2沖突。之前不知道原因&#xff0c;直接就是卸載重裝&#xff0c;累死我了。現在知道后&#xff0c;將解決方案記下&#xff0c;幫助后來者繼續前行。 管理員打開cmd&#xff0c;輸入 …

并發編程(多進程1)

一 multiprocessing模塊介紹 python中的多線程無法利用多核優勢&#xff0c;如果想要充分地使用多核CPU的資源&#xff08;os.cpu_count()查看&#xff09;&#xff0c;在python中大部分情況需要使用多進程。Python提供了multiprocessing。 multiprocessing模塊用來開啟子進…

LInux 下文件包的使用

1 .deb   http://wiki.ubuntu.org.cn/MySQL%E5%AE%89%E8%A3%85%E6%8C%87%E5%8D%97 2 .rpm

@RequiresPermissions 注解說明

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 RequiresAuthentication 驗證用戶是否登錄&#xff0c;等同于方法subject.isAuthenticated() 結果為true時。 RequiresUser 驗證用戶…

千位分隔符轉換為數字

最近下載了akshare里面的數據&#xff0c;然后發現有些數據格式為1,300這種格式&#xff0c;為str格式&#xff0c;但是又無法直接強制轉換之類方式&#xff0c;特地尋求答案&#xff0c;并做筆記&#xff0c;留待自己與后來者一起避坑。 from locale import * atof(123,456)…

一本通1629聰明的燕姿

1629&#xff1a;聰明的燕姿 時間限制: 1000 ms 內存限制: 524288 KB【題目描述】 城市中人們總是拿著號碼牌&#xff0c;不停尋找&#xff0c;不斷匹配&#xff0c;可是誰也不知道自己等的那個人是誰。 可是燕姿不一樣&#xff0c;燕姿知道自己等的人是誰&#xff0c;…

IT職場人生系列之二十四:程序員如何增加收入

這是IT職場人生系列的第二十四篇。&#xff08;序言&#xff0c;專欄目錄&#xff09; 程序員的收入是廣受關注的問題&#xff0c;很多人從業3&#xff5e;5年之后就會遇到這個收入瓶頸。盡管物價不斷上漲&#xff0c;程序員尤其是初、中級程序員的收入不升反降。即使上次在某…

ASP 代碼當前記錄集不支持更新問題的解決辦法。

錯誤類型&#xff1a;ADODB.Recordset (0x800A0CB3)當前記錄集不支持更新。這可能是提供程序的限制&#xff0c;也可能是選定鎖定類型的限制。 /Model/manage/Admin_Admin.asp, 第 35 行 找到放在數據庫文件的--- 右鍵--》屬性---》安全----》添加IIS來賓用戶---》權限為&#…

@PathVariable 注解 說明

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 PathVariable 映射 URL 綁定的占位符 帶占位符的 URL 是 Spring3.0 新增的功能&#xff0c;該功能在SpringMVC 向 REST 目標挺進發展過…

數據清洗,篩選

本人在私募&#xff0c;負責數據收集以及清洗&#xff0c;就是包括收集數據&#xff0c;按照領導要求&#xff0c;選出滿足條件的數據&#xff0c;用于校驗策略是否正確。 現在就在這進行代碼上傳&#xff0c;即用于自己總結整理&#xff0c;也用于供大家學習了解&#xff0c;實…

JS媒體查詢

樣式的改變使用C3的媒體查詢 行為和功能的改變使用JS的媒體查詢 matchMedia()方法參數可寫任何一個CSSmedia規則&#xff0c;返回的是新的MediaQueryList對象&#xff0c;該對象有兩個屬性 media&#xff1a;查詢語句的內容matches&#xff1a;檢查查詢結果&#xff0c;返回boo…

Ruby初步介紹

Ruby是腳本語言,與傳統的C, Java不同的是,它不需要經過編譯,而是直接可以被執行 Ubuntu下執行第一個ruby腳本 print("Hello David, This is your first Ruby script.\n") davidubuntu:~/RubyTrain/Basic$ ruby Hello.rb 運行結果: Hello David, This is your first R…

C/C++ main用法總結

今天看到一篇很好的文章&#xff0c;詳細的講解了C、C中的main函數&#xff0c;以及returne的用法。轉載過來大家一起分享下。轉自&#xff1a;http://www.cnblogs.com/ct6816678/archive/2012/10/26/2741824.htmlreturn是C預定義的語句&#xff0c;當return語句提供了一個值時…

如何將數據寫入excel中,而不覆蓋原有數據

之前直接用pandas庫&#xff0c;然后to_excel&#xff08;&#xff09;&#xff0c;結果直接將原始數據直接覆蓋&#xff0c;幸虧有備份。&#xff08;友善提醒&#xff0c;做數據處理之前&#xff0c;先將數據本地備份一份&#xff0c;確認完全沒有問題&#xff0c;然后還是備…