深度剖析指標------1
眾所周知,指標是c語言的靈魂所在,也是c語言的難點所在,很多人在學習這部分的時候都感到非常困難,然而只要你靜下心來慢慢“品嚐”,你會發現,指標非常的靈活,C語言之精髓!!
指標是什麼?這個問題聽起來真的不陌生,可能你自己都常常問你自己指標到底是什麼?
---------指標就是地址,地址就是指標
我們可以把計算機記憶體用一個方塊來模擬,把這個方塊切成若干個,每一塊大小為一個位元組(八個位元位),每一塊用一個數來標識(地址),當我們想找到某一塊時只需要知道這一塊的標識數(地址),由於這個標識數(地址)具有很強的指向性,所以我們稱它為指標。
那麼“指標變數”又是什麼呢,指標變數是我們定義的一個變數,這個變數用來存放指標
實際上,我們不要去糾結這兩個名詞,我們把指標變數一般就叫指標,區分它們並沒有實際意義。
一、字元指標
char ch = 'a';
char* p =&ch;
printf("%c", *p);
圖中的p就是一個字元指標,下面來看另一種常用字元指標
char* p = "i love you";
printf("%s\n", p);
這裡的p也是一個字元指標,那麼這個指標到底是啥?如果我們直接用%p打印出p,我們將得到一個地址,那麼這個地址到底是誰的地址呢?對,他就是首字元的地址,在這裡即是i的地址。
下面來看一道經典例題:
char str1[] = "i love you"; char str2[] = "i love you"; char* str3 = "i love you"; char* str4 = "i love you"; if (str1 == str2) printf("1 and 2 is same\n"); if (str3 == str4) printf("3 and 4 is same\n");
輸出結果為:3 and 4 is same
那為什麼會這樣呢?
因為這裡的str3和str4指向的是同一個字串,c/c++會把字元常量單獨放到一個區域(字元常量區),當要用到他們時,就可以用指標解引用來使用它們。理所當然,這裡的str3和str4不能再被更改否則會報錯。 str1和str2都是陣列,在C語言中,兩個陣列的地址(陣列名)怎麼可能相等呢,編譯器不可能給他們開闢在同一個地址空間,所以這裡肯定不一樣唄!!!
二、指標陣列和陣列指標
很顯然,指標陣列是陣列, 陣列指標是指標
那他們的用途分別是什麼呢?
指標陣列:
定義:
int* arr1[10]; //存放整形指標 char* arr2[10]; //存放字元指標
這裡指標陣列不再過多介紹,我們前面有一篇文章專門介紹了指標陣列和陣列指標,裡面還有一些經典例子。
陣列指標:
定義:
int (*p1)[10];
char (*p2)[10];
這裡就有一些小夥伴開始搞不清楚陣列指標和指標陣列的寫法,真的很像耶✌!!這裡有一個小訣竅來辨別他們:我們得知道[ ]的優先順序高於 * ,所以沒加括號時會與[ ]先結合,那麼他就是一個數組(指標陣列),而括號括起來後,他就是一個指標(陣列指標);
知識法寶:定義一個數組arr,區別arr和&arr
有人會一本正經的回答,它兩不就一樣嘛!確實,他倆的值都一樣,但意義卻大不相同,你需要切記:陣列名“永遠”代表陣列首元素的地址(除1. 用sizeof求取它的長度 2.取地址陣列名這兩種特殊情況外)。而&arr代表這個陣列的地址。
你可以打印出 arr+1 和 &arr+1 的值,他們的值是不會相同的!!
下面看這幾條語句:
int arr[10] = {0};
int (*p1)[10];
int (*p2)[8] = &arr; //警告 (緯度應該一致)
p1 = &arr;
p1 = arr; //警告 (應該取該陣列的地址,而不是首元素的地址)
好了,那麼陣列指標一般的用途到底是啥?我們看下面的程式碼:
#include<stdio.h>
void print(int (*p)[3], int row, int col);
int main()
{
int arr[2][3] = {{2,3,4},{5,6,7}};
print(arr, 2, 3);
return 0;
}
void print(int (*p)[3], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for(j = 0; j < col; j++)
printf("%d ", p[i][j]);
printf("\n");
}
}
結果為:
這是陣列指標的一個典型運用,用它來傳參多維陣列,這裡該怎樣使用它來傳參呢?
切記下面的話:
陣列 傳參 會 降維 成 “指向其內部元素” 的 指標;
當多維陣列傳參時,用陣列名接收時,只能省去離陣列名最近的那個緯度;
三、指標傳參:
一級指標傳參
可以用來接收一維陣列、一級指標等等,這裡比較簡單,不再過多介紹
二級指標傳參:
下面看一段程式碼:
#include<stdio.h>
void test(char** p)
{
printf("lalala\n");
}
int main()
{
char c = 'b';
char* pc = &c;
char** ppc = &pc;
char* arr[10];
test(&pc);
test(ppc);
test(arr);
return 0;
}
該程式碼體現了幾種二級指標的傳參(該程式碼無警告無錯誤)