目录
1.数组名的理解
2. 使用指针访问数组
3. 一维数组传参的本质
4. 冒泡排序
5. 二级指针
6.指针数组
7.指针数组模拟二维数组
正文:
1.数组名的理解
数组名实质是数组首元素的地址。验证代码如下:
int arr[10] = {0}; printf("%p\n",&arr[0]); printf("%p\n",arr);//二者结果相同这里有一段代码,又会提出新的问题:
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; printf("%d\n",sizeof(arr)); //输出结果为:40数组名确实是数组的首元素地址,但是有两个例外的情况:
(1)sizeof(数组名),此时数组名表示整个数组,求的是整个数组的内存大小(单位字节)
(2)&数组名,这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址与数组首元素的地址不同)
测试代码:
int arr[10] = {1,2,3,4,5,6,7,8,9,10}; printf("&arr[0]=%p\n",&arr[0]); printf("arr =%p\n",arr); printf("&arr =%p\n",&arr); //三者输出结果完全相同那么 arr 与 &arr 之间的到底有什么区别呢?进行数组+-整数试试:
int arr[10] = {1,2,3,4,5,6,7,8,9,10}; printf("&arr[0] = %p\n",&arr[0]); printf("arr = %p\n",arr); printf("&arr = %p\n",&arr); printf("&arr[0] + 1 = %p\n",&arr[0] + 1); printf("arr + 1 = %p\n",arr + 1); printf("&arr + 1 = %p\n",&arr + 1);代码结果:
&arr[0] = 0077F820 arr = 0077F820 &arr = 0077F820 &arr[0] + 1 = 0077F824 arr + 1 = 0077F824 &arr + 1 = 0077F848结论:在指针+-整数时,arr + 1 跳过的是数组的一个元素,而 &arr + 1 跳过的是整个数组,这就很好的解释了 &数组名 代表的是整个数组。
2. 使用指针访问数组
int arr[10] = {0}; int* parr = arr; //利用指针对数组进行输入 for(int i = 0;i < 10;i++) scanf("%d",p + i); //利用指针进行数组打印 for(int i = 0;i < 10;i++) printf("%d",*(p+i));//等价于 printf("%d",arr[i]);在上述代码中,不难看出:*(p + i) == p[ i ] ,又因为 arr 是数组首元素地址,则:
结论:arr[ i ] == *(arr + i) ;&arr[ i ] == arr + i
3. 一维数组传参的本质
问题:我们之前都是在函数外部计算数组的元素个数,那可以把数组传给一个函数后,函数内部求数组元素的个数吗?
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; } // 结果:sz1 = 10 sz2 = 1函数形参接收的是数组首元素地址,在函数内部写的 sizeof(arr) ,计算的是一个地址的大小,而不是一个数组的大小。
结论:
1. 数组名是数组首元素的地址,在数组传参的时候,传递的是数组名,本质上数组传参传递的是数组首元素的地址。
2. 一维数组传参,形参部分可以写成数组的形式,也可以写成指针的形式。
4. 冒泡排序
核心思想:两两相邻元素进行比较。
void bubble_sort (int arr[],int sz) { for(int i = 0;i < sz - 1;i++) { int flag = 1; for(int j = 0;j < sz - 1 - i;j++) { if(arr[j] > arr[j + 1]) { flag = 0; int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } if(flag == 1) break; } for(int i = 0;i < sz;i++) printf("%d ",*(arr + i)); } int main() { int arr[10] = {10,9,8,7,6,5,4,3,2,1}; int sz = sizeof(arr) / sizeof(arr[0]); bubble_sort(arr,sz) return 0; }5. 二级指针
指针变量也是变量,是变量就会有地址,那么指针变量存放在哪里?
存放指针变量地址的变量,称为二级指针。
二级指针变量的运算:
以上述代码为例:
*ppa == pa;**ppa == a;一个 * 解引用一次,两个 * 解引用两次。
6.指针数组
指针数组是存放指针的数组。
parr 是一个数组,数组有 3 个元素,每个元素的类型是 int *
指针数组的每个元素是个地址,又可以指向一块区域。
7.指针数组模拟二维数组
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* par[3] = {arr1,arr2,arr3}; for(int i = 0;i < 3;i++) { for(int j = 0;j < 5;j++) printf("%d ",parr[i][j]); printf("\n"); return 0; }parr[ i ] 是访问 parr 数组的元素,parr[ i ]找到的数组元素指向了整型一维数组,parr[ i ][ j ]
就是整型一维数组中的元素。
二维数组每一行在内存空间上都是连续的,上述代码模拟出二维数组的效果,但是并非完全等同于二维数组。
欢迎大家交流与指正,感谢阅读。