指針和數組的關系,指針和函數的關系
1、指針和一維數組的關系
數組名是一個指針常量,表示數組第一個元素的的起始位址。
如 int a[5]; a表示數組第一個元素a[0]的起始位址&a[0]。
換句話說:數組名就是數組的首位址。
arr[0] = 1; arr[2] = 3;
arr[1] = 2; arr[3] = 4;
int *p;
p = arr; //一個一級指針指向了一個一維數組,那麼指針的偏移和數組的偏移是一模一樣的。
*(p+0) 的值等于 arr[0] (p+2) 的值等于 arr[2]
*(p+10 的值等于 arr[1]
*(p+0) ==1; //指針偏移後解引用;
*(p+1) ==2;
數組名可以了解為是一個被const修飾的指針,絕對不可以改變其指向,因為一旦改變了指向,那麼就沒有人可以找到該數組的位置。
2、指針和字元數組的關系
char []可以來儲存多個字元。
例如:
char ch[6] = {'h','e','l','l','o','\0'}; //當char[]最後一個字元為‘\0’時,是一個字元串。
char ch[6] = "hello";
char ch[] = "hello";
//以上儲存在棧記憶體中,可以被修改。
char *p = "hello"; //儲存在常量區,不可以被修改。
3、指針數組,數組指針
指針數組:是一個數組,隻不過其中的每一個元素都是指針。
文法:資料類型 *數組名[數組大小] int *p[5]
int a,b,c;
int *p[4] = {&a,&b,&c,NULL} ;
例如主函數中:
主函數的棧區有一個叫argv的數組,這個數組的元素是你輸入的參數的位址,指向着隻讀資料區。
例如:
char p[4] = {“abc”,“asd”,“qwe”,“xyz”};
p就是我定義的一個指針數組,他有四個元素,每個元素都是char 類型的指針,指向字元串常量。
數組指針:本實質是一個指針,專門用來在數組之間偏移固定大小。
文法:資料類型 (*變量名)[一次偏移的大小] int(*pa)[5];
pa是一個指針指向一個char [5]的數組。
pa的一次偏移是5個int數的大小,專門用來指向二維數組。
定義 int (*p)[n];
()優先級高,首先說明p是一個指針,指向一個整型的一維數組,這個一維數組的長度是n,也可以說是p的步長。也就是說執行p+1時,p要跨過n個整型資料的長度。
如要将二維數組賦給一指針,應這樣指派:
int a[3][4];
int (*p)[4]; //該語句是定義一個數組指針,指向含4個元素的一維數組。
p=a; //将該二維數組的首位址賦給p,也就是a[0]或&a[0][0]
p++; //該語句執行過後,也就是p=p+1;p跨過行a[0][]指向了行a[1][]
4、指針和函數的關系
函數傳參
值傳遞:僅僅将自己的值指派給形參
位址傳遞:将自己的位址交給形參,可以通過形參修改其值
指針函數:傳回值是一個指針的函數就叫指針函數
char *my_strcpy()
{
代碼;
return NULL;
}
函數指針:本質上是一個指針,用來儲存某個函數的入口位址,函數名就是函數的入口位址
如果在程式中定義了一個函數,那麼在編譯時系統就會為這個函數代碼配置設定一段存儲空間,這段存儲空間的首位址稱為這個函數的位址。而且函數名表示的就是這個位址。既然是位址我們就可以定義一個指針變量來存放,這個指針變量就叫作函數指針變量,簡稱函數指針。
用法:函數傳回值類型 (* 指針變量名) (函數參數清單);
int (*p)(int a,int b);//如果想儲存某個函數的位址,就将該函數原封不動的複制過來,将函數名改為指針名
//該函數指針類型:傳回值為int,參數為兩個整型數的類型
int func(int a); //聲明一個函數
int (*p) (int b); //定義一個函數指針
p = func; //将func函數的首位址賦給指針變量
指派時函數 func 不帶括号,也不帶參數。由于函數名 func 代表函數的首位址,是以經過指派以後,指針變量 p 就指向函數 func() 函數的首位址了。
例如:
#include <stdio.h>
int sub(int a,int b)
{
return a-b;
}
void fun(int a,int b,int (*p)(int a,int b)) // 定義函數指針作為參數
{
printf("%d\n",p(a,b));
}
void main(int argc,char *argv[]) //主函數 調用fun函數時 第3個參數是函數名。
{
fun(1,2,sub);
}