--指针访问数组在前面已经学过,有着多种形式:
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* pa = &arr[0];
printf("arr[0] = %p\n", pa);
int* pb = arr;
printf("arr = %p\n", pb);
return 0;
}
--发现,两种方式结果相同,就证实了:数组名是数组首元素的地址!
--但注意不是所有使用数组名的情况都代表首元素地址,两个特例注意:
--来几个例子加深理解:
--例一
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr);
printf("%d\n", sz);
return 0;
}--代码输出为40,就代表了sizeof中的数组名代表的是整个数组而不是首元素地址。
--例二
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("arr = %p\n", arr);
printf("&arr = %p\n", &arr);
printf("arr+1 = %p\n", arr+1);
printf("&arr+1 = %p\n", &arr+1);
return 0;
}
--这个例子就解释了arr(&arr[0])与&arr的区别:
--看输出结果
--现在对数组的不同含义应该有了清楚的认知。
--在前面了解了数组名的知识,下面就可以根据数组的特点,用指针访问数组。
int main()
{
int arr[10] = {0};
//求数组长度
int sz = sizeof(arr) / sizeof(arr[0]);
//定义指针变量
int* p = arr;
//输入
int i = 0;
for (i = 0; i < sz; i++)
{
scanf("%d", p + i);//指针变量p存储的是地址
//或arr+i,跳过过i个元素
}
//打印
for (i = 0; i < sz; i++)
{
printf("%d ", *(p + i));
//或*(arr+i)或arr[i]
}
return 0;
}--在上面知道:arr与p是等价的,那就可以将arr与p对调--p[ i ]访问数组。
--本质*(p+i)等价于p[ i ]等价于*(arr+i)。要知道数组元素的访问在编译器处理的时候,也是转换成首元素的地址+偏移量求出元素的地址,然后解引用来访问的。
--学习函数时,知道数组是可以传递给函数的,在这就了解一下数组传参的本质。
--在前面,函数部分计算数组大小的时候都是在主函数中计算,那现在可不可以将数组传给函数来计算呢?
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;
}
--在函数内部计算并没有正确的到结果,哎,这就涉及到函数传参的本质了。
--已经知道,数组名代表首元素的地址,传参时就变成了传地址,所以形参应该是指针变量 。
--函数内部sizeof(arr)计算的就是地址(指针变量)的大小,因此在函数内部无法完成操作!
--对于地址大小在指针(一)说过
--32位平台(VSx86)下地址是32个bit位(即4个字节); --64位平台(x64)下地址是64个bit位(即8个字节);
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;
}总结:一维数组传参,形参的部分可以写成数组的形式,也可以写成指针的形式。
--冒泡排序核心思想:两两相邻元素进行比较。
--对数组元素进行升序排列,了解冒泡排序:
void bubble_sort(int* arr, int sz)
{
//趟数
int i = 0;
for (i = 0; i < sz - 1; i++)
{
//一趟内部比较
int flag = 1;//假设有序
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = 0;
}
}
if (flag == 1)
break;
}
}
void printf_arr(int* arr, int sz)
{
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
//冒泡排序
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
//将数组元素排成升序
//冒泡排序-两两相邻元素比较
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz);
printf_arr(arr, sz);
return 0;
}--指针变量也是变量,那么存放一级指针变量地址的指针变量为二级指针变量。

--对于二级指针变量的运算:
int b = 20; *ppa = &b;//等价于pa = &b
**ppa = 30;() 等价于 *pa = 30;即a = 30
--先类比数组,说整型数组是存放整形数据的数组,那么知道指针数组是存放指针的数组。


--指针数组每个元素都是用来存放地址的,每个地址又可以指向一块区域。
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 2,3,4,5,6 };
int arr3[] = { 3,4,5,6,7 };
//数组名是数组首元素的地址,类型是int,存放在arr数组中
int* arr[] = { arr1, arr2, arr3 };
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
--arr[i]是访问arr数组的元素,arr[i]找到的数组元素指向了整型⼀维数组,arr[i][j]就是整型⼀维数组中的元素。
结语:本篇内容就到这里了,主要分享了指针数组的一些内容,后续仍会分享指针的相关知识;指针的内容需要反复研读 ,如果这篇文章对你的学习有帮助的话,欢迎一起讨论学习,你这么帅给个三连吧~~~
复习: