首頁 > 軟體

C語言超詳細講解指標的使用

2022-05-21 13:01:40

指標概述

C語言中指標也可以認為是一種型別,不同於數值型和字元型的型別。推演過去指標變數也就是相當於不同的變數型別,不同於數值變數、字元型變數、字串變數。

指標變數兩種型別:自身型別和指向的型別

自身型別:將變數名去掉,剩下的就是指標變數型別。

指向型別:將變數名和離它最近的一個*去掉,剩下的型別就是指標指向的型別

int num = 10;
int* p = NULL;
p = #

如程式碼中 指標變數的自身型別是 int * 型;指向型別是 int 型。

自身型別

自身型別是指變數p本身的型別,變數p中放的是地址內容,地址指向的是放整型的資料,為什麼需要說是指向整型的地址呢?因為不同型別資料佔據的不同大小的一整塊記憶體,整型是一個佔4位元組大小的一個整體記憶體,字元型是一個佔2個位元組大小的一個整體記憶體,編譯器不會把它們拆分開。如定義了一個int型變數,它的地址是0x7fffffff00,緊接著馬上定義一個char型變數,他的地址就直接到了0x7fffffff04。從0x7fffffff00 ~ 0x7fffffff04中間不會再被分開了放int型資料,0x7fffffff04 ~ 0x7fffffff06中間不分開放char型資料。

所以 自身型別 是基本型別 + *組合而成,雖然裡面放的都是地址,但是地址指向的一整塊內容是有區別的。

指向型別

指向型別 是指 指標變數中放置的地址是指向的內容型別。

int num = 10;
int* p = NULL;
p = #
int** pp = NULL;
pp = &p;

這是一個二級指標,指向的型別是int*,說明變數pp指向的是指標型別的資料。

程式碼例子

程式碼1

 #include <stdio.h>
 int main()
 {
     int num = 100;
     printf("num = %d, num address = %#lxn", num, &num);
     //num = 100, num address = 0x7ffd4376ff4c   
     int* p = NULL;
     p = &num;
     printf("*p = %d, p =  %#lx, &p = %#lxn", *p, p, &p);
     //*p = 100, p =  0x7ffd4376ff4c, &p = 0x7ffd4376ff40
     int** pp = NULL;
     pp = &p;
     printf("**pp = %d, *pp = %#lx, pp = %#lxn", **pp, *pp, pp);
     //**pp = 100, *pp = 0x7ffd4376ff4c, pp = 0x7ffd4376ff40
     int arr[5]= {10,20,30,40,50};
     printf("arr address = %#lx, arr[0] address = %#lx, arr[0] = %dn",arr,&arr[0],arr[0]);
     //arr address = 0x7ffd4376ff20, arr[0] address = 0x7ffd4376ff20, arr[0] = 10    
     int* parr = NULL;
     parr = arr;
     printf("parr = %#lx, *parr = %d, *(parr+2) = %dn",parr,*parr,*(parr+2));
     //parr = 0x7ffd4376ff20, *parr = 10, *(parr+2) = 30
     char str[6]= {'a','d','m','i','n',''};
     printf("str address = %#lx, str[0] address = %#lx, str[1]= %cn", str, &str[0],str[1]);
     //str address = 0x7ffd4376ff10, str[0] address = 0x7ffd4376ff10, str[1]= d  
     char* pstr = NULL;
     pstr = str;
     printf("pstr = %#lx,*pstr = %c,*(pstr+2)= %cn",pstr,*pstr,*(pstr+2));
     //pstr = 0x7ffd4376ff10,*pstr = a,*(pstr+2)= m
     char str2[6] = "admin";
     printf("str2 = %#lx, str2[0] address = %#lx, str2 = %s, str2[1]= %cn",str2,&str2[0],str2,str2[1]);
     //str2 = 0x7ffd4376ff00, str2[0] address = 0x7ffd4376ff00, str2 = admin, str2[1]= d
     char* pstr2 = NULL;
     pstr2 = str2;
     printf("pstr2 = %#lx, pstr2 = %sn",pstr2, pstr2);
     //pstr2 = 0x7ffd4376ff00, pstr2 = admin       
 }

程式碼2

#include <stdio.h>
int main()
 {
     float num = 10;
     printf("num = %f, &num = %#lxnn", num, &num);
     //num = 10.000000, &num = 0x7ffcdf7ffd94
     float* pnum = &num;
     printf("*pnum = %f, pnum = %#lx, &pnum = %#lxnn ", *pnum, pnum, &pnum);
     //*pnum = 10.000000, pnum = 0x7ffcdf7ffd94, &pnum = 0x7ffcdf7ffd88
     float** p_pnum = &pnum;
     printf("**p_pnum = %f, *p_pnum = %#lx, p_pnum = %#lxnn",**p_pnum,*p_pnum,p_pnum);
     //**p_pnum = 10.000000, *p_pnum = 0x7ffcdf7ffd94, p_pnum = 0x7ffcdf7ffd88
     char arr[10] = {'a','d','m','i','n'};
     printf("arr[0]= %c, arr[5]= %c, arr[6]= %c, arr = %sn",arr[0],arr[5],arr[6],arr);
     printf("&arr[0]= %#lx, &arr[1]= %#lx, arr= %#lxnn", &arr[0], &arr[1], arr);
     //arr[0]= a, arr[5]= , arr[6]= , arr = admin
     //&arr[0]= 0x7ffcdf7ffd70, &arr[1]= 0x7ffcdf7ffd71, arr= 0x7ffcdf7ffd70
     char* parr = NULL;
     parr = arr;
     printf("*parr = %c, *(parr+4)=%c, *(parr+5)=%c, parr = %sn",*parr,*(parr+4),*(parr+5),parr);
     printf("parr = %#lx, parr+4 = %#lx, parr+5= %#lxnn", parr, parr+4, parr+5);
     //*parr = a, *(parr+4)=n, *(parr+5)=, parr = admin
     //parr = 0x7ffcdf7ffd70, parr+4 = 0x7ffcdf7ffd74, parr+5= 0x7ffcdf7ffd75     
     char str[10]= "admin";
     printf("str[0]= %c, str[5]= %c, str[6]= %c, str = %sn",str[0],str[5],str[6],str);
     printf("&str[0]= %#lx, &str[1]= %#lx, str = %#lxnn", &str[0], &str[1], str);
     //str[0]= a, str[5]= , str[6]= , str = admin
     //&str[0]= 0x7ffcdf7ffd60, &str[1]= 0x7ffcdf7ffd61, str = 0x7ffcdf7ffd60
     char* pstr = NULL;
     pstr = str;
     printf("*pstr= %c, *(pstr+4)= %c, *(pstr+5)= %c, pstr = %sn", *pstr, *(pstr+4), *(pstr+5), pstr);
     printf("pstr = %#lx, pstr+4=%#lx, pstr+5= %#lxnn",pstr, pstr+4, pstr+5);
     //*pstr= a, *(pstr+4)= n, *(pstr+5)= , pstr = admin
     //pstr = 0x7ffcdf7ffd60, pstr+4=0x7ffcdf7ffd64, pstr+5= 0x7ffcdf7ffd65
 }

數值型指標

數值型指標: int* p;

如:

int num = 100;
int* p = &num;		//同時定義和初始化
int* p1 = NULL;		//定義
p1 = &num;			//初始化

字元型指標

字元型指標可以分為指標指向的是單字元還是字元陣列兩種

單字元

字元型指標: char* p;

char name = 'a';
char* p = &name;
printf("p = %c",*p);	//結果是 a

這裡需要注意需要用 預留位置 %c 去承接內容(或者說顯示內容)

字元陣列

字元型指標:char* p;

char arr[6] = {'a','d','m','i','n',''};
printf("arr = %s, arr = %#lxn",arr,arr);	//admin,0x7ffffffc0
printf("arr[0]= %c,arr[1]= %cn",arr[0],arr[1]);//a,d
char* parr = NULL;
parr = arr;     //也可以 parr =  &arr,但是編譯時會報warning
printf("parr = %s, parr = %#lxn", parr,parr);	//admin,0x7ffffffc0
printf("*(parr)= %c,*(parr + 1) = %cn",*parr, *(parr+1));  

這裡需要注意字元陣列末尾需要加‘’字元表示字元陣列結束,或者編譯器自己會自動加上,所以在定義字元陣列長度時需要加+1。

注意 字元陣列名既可以表示地址也可以表示整個字元陣列的內容,而不是第一個字元。相應的指標也是整個字元陣列的內容。

printf("arr = %cn", arr);		
printf("parr = %cn", parr);

以上兩行程式碼可以編譯過但是不能顯示內容,需要用預留位置%s去承接整個字元陣列內容。

字串型指標

字元型指標:char* p;

char str[5] = "admin";
printf("str = %s,str = %#lxn",str,str); // admin,0x7ffffffe0.
printf("str[0]= %c, str[1]= %cn",str[0],str[1]);	// a,d
char* pstr = NULL;
pstr = str;
printf("pstr = %s, pstr = %#lxn",pstr,pstr); // admin,0x7ffffffe0.
printf("*pstr = %c,*(pstr+1) = %cn",*pstr,*(pstr+1)); // a,d

如程式碼中結果顯示所示,字串陣列名即是地址,同時也是陣列內容,根據預留位置的不同顯示不同內容,預留位置為%s時顯示字串,%#lx顯示地址。同樣的對於賦值給的指標變數也具有同樣的功能。

但是如果這裡

printf("str = %cn",str);	//可以編譯過但是不顯示任何資訊

字元陣列總結

字元陣列和字串陣列名都可以即表示地址又表示地址對應的內容,注意看需要它以什麼形式顯示,顯示內容用%s,顯示地址用%#lx。

字元陣列和字串陣列名對應的地址都是第一個字元所在的地址。如上面的程式碼中 &arr[0] 和 arr 得到的地址相同

到此這篇關於C語言超詳細講解指標的使用的文章就介紹到這了,更多相關C語言指標內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com