目錄
一、數組名的理解
二、用指針訪問數組
三、一維數組傳參的本質
四、冒泡排序
五、二級指針
六、指針數組
七、指針數組模擬二維數組
八、結語
一、數組名的理解
數組名其實就是首元素的地址
int arr[3] = {1,2,3};
printf("arr :%p\n" ,arr);
printf("arr[0]:%p\n" ,&arr[0]);
可以看到,數組名確實就是首元素的地址,但是有沒有想到這個語句?
int r = sizeof(arr)/sizeof(arr[0]);
這是用來求數組的元素個數的,在這里,數組名是個例外,它表示整個數組
既然數組名就是首元素地址,那么 &arr 又代表這什么呢?
int arr[3] = {1,2,3};
printf("arr: %p\n",arr);
printf("arr+1: %p\n" ,arr+1);
printf("&arr: %p\n" ,%arr);
printf("&arr+1: %p\n" ,&arr+1);
可以看到,&arr 和 arr 的地址是一樣的,但是&arr 擁有的權限是整個數組,而arr的權限只有一個元素,因此,他們分別+1的結果就不同了
二、用指針訪問數組
通常我們訪問數組元素使用下標的
printf("%d ",arr[2]);
既然數組名就是首元素地址,那我是不是可以通過指針來訪問呢,比如解引用首元素的指針?
printf("%d ",*arr);
沒問題,而我們又知道數組在內存中的存儲是連續的,那我知道了首元素的地址,那我豈不是也可以找到其他元素的地址,然后對其解引用,就可以訪問其他數組元素了?
for(int i = 0; i<3;i++)
{printf("%d " ,*(arr+i));
}
沒有問題,到此,我們可實現用指針訪問數組了。
但是,你有沒有想過,數組名 arr 是地址,可以通過 arr[2] 來訪問第三個元素,而我們的指針也存放的是地址,那我們的指針可不可以也能這樣 P[2] 訪問其他元素呢?
int* p = arr;
for(int i = 0; i<3;i++)
{printf("%d ",p[i]);
}
也沒問題!是不是很震驚!當然,要注意的是,是用了方括號就不要再帶解引用了哦
我要開始搞事情了,由以上分析可得:*(p+i) == p[ i ] 而? *(p+i) == *(i+p) ==?i[ p ] 了?
int* p = arr;
for (int i = 0; i < 3; i++)
{printf("%d ",i[p]);
}
return 0;
成功了!是不是更感覺很震驚了!當然,這是另類的寫法,我們一般還是要按照常理出牌,不然會被說成是豬隊友的
三、一維數組傳參的本質
大家有沒有經歷過在自己寫的函數中,求數組長度是錯誤的!
void Fun_arr(int arr[])
{int sz = sizeof(arr)/sizeof(arr[0]);
}
為什么求出來是1呢,這是因為數組傳參本質上傳的就是首元素的地址,所以求出來只有一個元素
四、冒泡排序
核心思想:兩兩相鄰元素的比較
1 | 4 | 2 | 5 | 3 |
這是一個無序數列,現在我們要將其變為升序序列,那就先把第一個元素和第二元素比較,把大的方后面,1 小于4,所以不用管,接下來比較第二個元素和第三個元素,4大于2 ,我們需要把大的放后面,把2和4位置對調:
1 | 2 | 4 | 5 | 3 |
最后就變成了:
1 | 2 | 4 | 3 | 5 |
發現沒有,我們進行一次,就把最大的弄的最后面去了,那我們再多進行幾次,不就把第二大,第三大的也弄后面去了?
第二次:
1 | 2 | 3 | 4 | 5 |
這里剛好就完成了排序。冒泡排序需要視頻講解更方便,圖文講解起來比較費勁,我這里就就不多說了,下面是冒泡排序的代碼:
void Bubble_sort(int arr[], int sz)
{for (int i = 0; i < sz - 1; i++){for (int j = 0; j < sz - 1 - i; j++){if (arr[j] > arr[j+1]){//交換int mid = arr[j];arr[j] = arr[j + 1];arr[j + 1] = mid;}}}
}
五、二級指針
二級指針就是該指針指向的變量仍然是一個指針,相應的還有三級指針,n級指針
int a = 10;
int* pa = &a;
int** ppa = &pa;//這里的ppa就是二級指針了
int** ppa = &pa;? 這里的 int* 說明ppa指向的變量的類型,第二個 * 說明ppa是指針變量
當然你要是想找到a,就要對ppa進行兩次解引用。
六、指針數組
前面將指針的時候說了,有整型數組,里面放的全是整型,字符型數組,里面放的全是字符型,那么,指針數組里面放的全部都是指針嘍。
int a = 10;
int b = 20;
int c = 30;
int* pa = &a;
int* pb = &b;
int* pc = &c;
int* arr[3] = {pa,pb,pc};
七、指針數組模擬二維數組
為了鞏固指針數組的理解,我們需要完成一個任務:用指針數組模擬一個二位數組
在學習二維數組的時候,講了二維數組在內存中的存儲是一行挨著一行的,那我們可以把每行的首元素的地址作為一個數組的元素,具體來講就是這個樣子:
int arr1[] = {1,2,3,4,5};
int arr2[] = {2,3,4,5,6};
int arr3[] = {3,4,5,6,7};
int* str[] = {arr1,arr2,arr3};
for(int i = 0; i<3;i++)
{for(int j = 0; j<5;j++){printf("%d ", str[i][j] );}printf("\n");
}
關于這里的打印,前面說了,可以用指針加方括號的形式打印,所以就寫成了 str[ i ][ j ],因為? ? str[ i ] 表示的是一個地址嘛。
八、結語
指針的學習沒有終點。繼續探索,挑戰自己,你將發現C語言指針的強大之處,并能編寫出更高效、更靈活的代碼。愿你在C語言指針的世界里越走越遠,收獲滿滿!