1.数组名的理解
我们在使⽤指针访问数组的内容时,有这样的代码:
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int* p=&arr[0];
这⾥我们使⽤ &arr[0] 的⽅式拿到了数组第⼀个元素的地址,但是其实数组名本来就是地址,⽽且
是数组⾸元素的地址,我们来做个测试。
int main()
{
int arr[10] = { 1,2,4,5,6,7,8,9,10 };
printf("arr[0]=%p\n", &arr[0]);
printf("arr =%p\n", arr);
return 0;
}
输出结果为:
2.使⽤指针访问数组
有了对数组名的理解,再结合数组的特点,我们就可以很⽅便的使⽤指针访问数组了。
int main()
{
int arr[10] = { 0 };
int* p = arr;
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; i++)
{
scanf("%d ", p + i);//输⼊
}
for (int i = 0; i < sz; i++)//输出
{
printf("%d ", *(p + i));
}
return 0;
}
这里我们发现数组名和数组⾸元素的地址打印出的结果⼀模⼀样,其实数组名就是数组⾸元素(第⼀个元素)的地址。
这个代码搞明⽩后,我们再试⼀下,如果我们再分析⼀下,数组名arr是数组⾸元素的地址,可以赋值给p,其实数组名arr和p在这⾥是等价的。那我们可以使⽤arr[i]可以访问数组的元素,那p[i]是否也可以访问数组呢?
在第18⾏的地⽅,将*(p+i)换成p[i]也是能够正常打印的,所以本质上p[i]是等价于*(p+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;
}
输出结果为:
这里发现在函数内部是没有正确获得数组的元素个数。
这就要学习数组传参的本质了,上个⼩节我们学习了:数组名是数组⾸元素的地址;那么在数组传参的时候,传递的是数组名,也就是说本质上数组传参传递的是数组⾸元素的地址。
4. 冒泡排序
冒泡排序(Bubble Sort)是一种简单的排序算法。它重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
这个算法的名字由来是因为越小(或越大)的元素会经由交换慢慢“浮”到数列的顶端。
那么冒泡排序的核⼼思想就是:两两相邻的元素进⾏⽐较:
void bubble_sort(int arr[], int sz)//参数接收数组元素个数
{
int i = 0;
for (i = 0; i < sz - 1; i++)
{
int j = 0;
for (j = 0; j < sz - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
int main()
{
int arr[] = { 3,1,7,5,8,9,0,2,4,6 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
5. ⼆级指针
指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪⾥?
想象你有三个变量:一个整型变量 a,一个指针变量 p,和一个二级指针变量 q。它们的关系可以这样表示:
在这个结构中:
- a 是一个整型变量,它存储了一个值。
- p 是一个指针变量,它的值是 a 的地址。也就是说,p 指向 a。
- q 是一个二级指针变量,它的值是 p 的地址。也就是说,q 指向 p。
所以,如果你有一个二级指针 q,你可以通过以下步骤来获取它所指向的原始变量的值:
1.通过 q 获取它所指向的一级指针 p(即 *q)。
2.然后通过一级指针 p 获取它所指向的原始变量 a 的值(即 *p 或 a)。
这个过程通常被称为“解引用”。简而言之,二级指针提供了一种间接访问内存的方式,通过两级指针来访问原始数据。