目錄
一.數組名的理解
二.使用指針訪問數組
三.一維數組傳參的本質?
四.冒泡排序
五.二級指針?
六.指針數組
6.1--指針數組的定義
6.2--指針數組模擬二維數組
🔥個人主頁:@草莓熊Lotso的個人主頁
🎬作者簡介:C++方向學習者
📖個人專欄:《C語言》
一.數組名的理解
--在前面的學習中,我們使用指針訪問數組時一般會采用以下兩種形式,它們所到達的效果也是相同的。
#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int* pa = &arr[0];int* pb = arr;printf("&arr[0] = %p\n", pa);printf("arr = %p\n", pb);return 0;
}
在上述代碼中我們分別使用&arr[0]和arr的方式拿到了數組的第一個元素的地址,這是因為數組名本身就是地址,而且是數組首元素的地址。
但是有兩個例外我們需要注意一下:
- sizeof(數組名),sizeof中單獨放數組名,這?的數組名表示整個數組,計算的是整個數組的?小,單位是字節
- &數組名,這里的數組名表示整個數組,取出的是 整個數組的地址(整個數組的地址和數組首元素的地址是有區別的)
那么我們就通過兩個例子具體分析一下吧~
例子1:
#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };printf("%d\n", sizeof(arr));return 0;
}
如果arr是數組首元素的地址,那輸出的應該是4/8?,但這串代碼的輸出結果最后是40,這就證明的sizeof(數組名)計算的是整個數組的大小。
例子2:
#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };printf("&arr[0] = %p\n", &arr[0]);printf("&arr[0]+1 = %p\n", &arr[0] + 1);printf("arr = %p\n", arr);printf("arr+1 = %p\n", arr + 1);printf("&arr = %p\n", &arr);printf("&arr+1 = %p\n", &arr + 1);return 0;
}
我們來分步解析一下這串代碼:
- 我們可以發現光看&arr,arr,&arr[0]打印出來的地址并沒有任何區別,這是因為數組的起始地址也是首元素的地址,所以我們接下來對它們分別+1 來找區別。
- +1之后我們會發現,&arr[0]和&arr[0]+1相差4個字節,arr和arr+1 相差4個字節,但是&arr 和 &arr+1相差40個字節。
- 這是因為&arr[0] 和 arr 都是?元素的地址,+1就是跳過?個元素,但是&arr是數組的地址,+1 操作是跳過整個數組的。
到這里想必大家都對數組名的意義有了正確的理解,我們接著往下看吧。
二.使用指針訪問數組
--學習了前面的知識后,再結合數組的特點,我們就可以更方便的使用指針訪問數組了。
#include <stdio.h>
int main()
{int arr[10] = { 0 };//輸?int i = 0;int sz = sizeof(arr) / sizeof(arr[0]);//輸?int* p = arr;for (i = 0; i < sz; i++){scanf("%d", p + i);//scanf("%d", arr+i);//也可以這樣寫}//輸出for (i = 0; i < sz; i++){printf("%d ", *(p + i));//*(p+i)等價于*(arr+i)也可寫成arr[i]}return 0;
}
?通過上述代碼我們可知,在這里arr和p是等價的,那我們可以使用arr[i]訪問數組,是不是也可以使用p[i]呢?
答案是當然可以,其實本質上p[i]是等價于*(p+i)的,那么同理arr[i] 應該等價于 *(arr+i),數組元素的訪問在編譯器處理的時候,也是轉換成?元素的地址+偏移量求出元素的地址,然后解引?來訪問的,所以這幾個使用那個都可以正確的打印出來結果。
還有一個比較有意思的等價關系給大家分享一下,但是不推薦使用:
arr[i] == *(arr+i) == *(i+arr) == i[arr]
大家可以發現,后面兩個等價的很怪,但確實是可行的,其實就是用了交換律而已。
三.一維數組傳參的本質?
--數組我們學過了,之前也講了,數組是可以傳遞給函數的,這個小節我們討論?下數組傳參的本質。
#include <stdio.h>
void test(int arr[])
{int sz2 = sizeof(arr) / sizeof(arr[0]);printf("sz2 = %d\n", sz2);
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };int sz1 = sizeof(arr) / sizeof(arr[0]);printf("sz1 = %d\n", sz1);test(arr);return 0;
}
我們通過上面這串代碼的輸出結果可以看出在函數內部沒有正確獲得數組的元素個數。這就涉及到數組傳參的本質了。
void test(int arr[])//參數寫成數組形式,本質上還是指針
{printf("%d\n", sizeof(arr));
}
void test(int* arr)//參數寫成指針形式
{printf("%d\n", sizeof(arr));//計算?個指針變量的??
}
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };test(arr);return 0;
}
?總結:一維數組傳參,形參的部分可以寫成數組的形式,也可以寫成指針的形式。
四.冒泡排序
--冒泡排序的核心思想:兩兩相鄰的元素進行比較。
//方法一
#include<stdio.h>
#include<string.h>void bubble_sort(int arr[], int sz)
{int i = 0;//趟數=元素個數-1=sz-1;for (i = 0;i < sz - 1;i++){int j = 0;//每一趟要比較的次數=元素個數-當前趟數-1=sz-i-1;for (j = 0;j < sz - i - 1;j++){if (arr[j] > arr[j + 1]){int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}
}
void print_arr(int arr[], int sz)
{for (int i = 0;i < sz;i++){printf("%d ", arr[i]);}
}
int main()
{int arr[10] = { 0 };//如果是arr[],后面就無法自己輸入數字,要注意int sz = sizeof(arr) / sizeof(arr[0]);printf("請輸入待排序的數字: ");for (int n = 0;n < sz;n++){scanf("%d", arr + n);}bubble_sort(arr, sz);printf("排序完成后的數字是: ");print_arr(arr, sz);return 0;
}
//方法二--優化
#include<stdio.h>
#include<string.h>
void bubble_sort(int arr[], int sz)
{int i = 0;//趟數=元素個數-1=sz-1;for (i = 0;i < sz - 1;i++){int j = 0;int flag = 0;//假設這趟是有序的//每一趟要比較的次數=元素個數-當前趟數-1=sz-i-1;for (j = 0;j < sz - i - 1;j++){if (arr[j] > arr[j + 1]){int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;flag = 0;//只要這趟有一次發生交換的,則無序}}if (flag == 1);//這一趟一次交換都沒發生就說明已經有序了,不用繼續排序了break;}
}
void print_arr(int arr[], int sz)
{for (int i = 0;i < sz;i++){printf("%d ", arr[i]);}
}
int main()
{int arr[10] = { 0 };//如果是arr[],后面就無法自己輸入數字,要注意int sz = sizeof(arr) / sizeof(arr[0]);printf("請輸入待排序的數字: ");for (int n = 0;n < sz;n++){scanf("%d", arr + n);}bubble_sort(arr, sz);printf("排序完成后的數字是: ");print_arr(arr, sz);return 0;
}
優化后的方法可以減少比較的次數,大大減少了程序運行的時間。
五.二級指針?
?--指針變量也是變量,是變量就有地址,那指針變量的地址存放在哪里呢。
那就是存放在二級指針里。
對于二級指針的運算有:
- *ppa 通過對ppa中的地址進?解引?,這樣找到的是 pa ,*ppa 其實訪問的就是?pa 。
1? int b = 20;2? *ppa = &b;//等價于 pa = &b;
- **ppa 先通過 *ppa 找到 pa ,然后對 pa 進?解引?操作:*pa ,那找到的是 a?
1 **ppa = 30;2 //等價于*pa = 30;3 //等價于a = 30;?
六.指針數組
6.1--指針數組的定義
--我們先來思考一下指針數組是指針還是數組呢?

?指針數組的每個元素都是用來存放地址(指針)的。指針數組的每個元素都是地址,又可以指向一塊區域。
6.2--指針數組模擬二維數組
#include <stdio.h>
int main()
{int arr1[] = { 1,2,3,4,5 };int arr2[] = { 2,3,4,5,6 };int arr3[] = { 3,4,5,6,7 };//數組名是數組首元素的地址,類型是int*,所以可以存放在parr數組中int* parr[3] = { arr1, arr2, arr3 };int i = 0;int j = 0;for (i = 0; i < 3; i++){for (j = 0; j < 5; j++){printf("%d ", parr[i][j]);}printf("\n");}return 0;
}
parr[i]是訪問parr數組的元素,parr[i]找到的數組元素指向了整型?維數組,parr[i][j]就是整型?維數組中的元素。
往期回顧:
【C語言】--指針超詳解(一)
【C語言】--指針超詳解(二)
?結語:本篇文章就到此結束了,繼前面兩篇文章后在此篇文章中給大家分享了大量數組和指針之間相聯系的知識點,還有冒泡排序等,如果文章對你有幫助的話,歡迎評論,點贊,收藏加關注,感謝大家的支持,后續會繼續更新指針相關內容。