数组名的理解

数组名本来就是地址,来做一个测试

1
2
3
int arr[5] = { 1,2,3,4,5 };
printf("%p\n", arr);
printf("%p\n", &arr[0]);


可以看到数组名本来就是地址,是数组首元素的地址

那么就可以使用数组名完成遍历数组

1
2
3
4
5
6
int arr[5] = { 1,2,3,4,5 };
for (int i = 0;i < 5;i++)
{
int n = *(arr + i);
printf("%d ", n);
}

数组名通常来说就是数组首元素的地址,但是有两个特殊情况

1
2
3
4
int arr[5] = { 1,2,3,4,5 };
printf("%p\n", &arr[0] + 1);
printf("%p\n", &arr + 1);
printf("%zd\n", sizeof(arr));

在 sizeof() 中的数组名表示的是整个数组

&arr 取出来的是整个数组的地址

使用指针变量访问数组

既然数组名是数组首元素的地址

那么是否可以将数组名放在一个指针变量中,然后用这个指针变量访问数组

1
2
3
4
5
6
7
8
9
10
11
int arr1[5] = { 0 };
int* p1 = arr1;
for (int i = 0;i < 5;i++)
{
scanf("%d", p1 + i);
}

for (int i = 0;i < 5;i++)
{
printf("%d ", p1[i]);
}

一维数组传参的本质

一维数组传参的本质实际上传的是数组首元素的地址而非是将整个数组传过去

1
2
3
4
5
6
7
8
9
void test(int arr[])
{
int sz = sizeof(arr) / sizeof (arr[0]);
printf("%d\n",sz);
}

int arr[10] = { 0 };
test(arr);
printf("%d\n",sizeof(arr) / sizeof(arr[0]));


可以看到函数内部并没有正确获取数组的个数。

这可以证明函数形参接受到的数组名实际上是首元素的地址,在函数内部调用

sizeof(arr) 计算的实际上是一个地址的大小而不是一个数组的大小。

二级指针

用于存放指针变量的地址的变量称为二级指针

对于二级指针,同样可以使用 * 操作符

1
2
3
4
5
6
int a = 10;
int* pa = &a;
int** ppa = &pa;
printf("%p\n", pa);
printf("%p\n", *ppa);
printf("%d\n", **ppa);


指针数组

专门用于存放指针的数组称为指针数组

1
2
3
4
5
6
7
8
9
10
11
12
13
int arr1[5] = { 1,2,3,4,5 };
int* parr1[5];
for (int i = 0;i < 5;i++)
{
// 往 parr1 中放入 arr1 中对应下标的元素的地址
parr1[i] = arr1 + i;
}

for(int i = 0; i < 5;i++)
{
// 每一个都是指针,要解引用
printf("%d ", *parr1[i]);
}

指针数组模拟二维数组

可以利用指针数组模拟二维数组

1
2
3
4
int arr1[3] = { 1,2,3 };
int arr2[3] = { 4,5,6 };
int arr3[3] = { 7,8,9 };
int* parr[3] = { arr1,arr2,arr3 };

上述代码 parr[0] 等价于 arr1

parr[1] 等价于 arr2

parr[2] 等价于 arr3

1
2
3
4
5
6
7
8
9
10
11
12
int arr1[3] = { 1,2,3 };
int arr2[3] = { 4,5,6 };
int arr3[3] = { 7,8,9 };
int* parr[3] = { arr1,arr2,arr3 };
for (int i = 0;i < 3;i++)
{
for (int j = 0;j < 3;j++)
{
printf("%d ", parr[i][j]);
}
printf("\n");
}

利用指针变量进行冒泡排序

冒泡排序就是数组中相邻两个数进行比较,如果存在大小关系按需求进行交换位

置。

当一轮比较下来,该数组中最小(最大)的数就会被放在数组的末尾

在下一轮比较中,就不需要比较上一轮已经被置于末尾的数。

假设当前比较轮次为 i,数组长度为 sz ,那么当前这轮比较次数为 sz - i 次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
nt arr[10] = { 53,65,88,75,10,69,62,40,57,99 };
int* parr = arr;
for (int i = 0;i <= 9;i++)
{
int flag = 0;// 通过这个判断需不需要结束循环
for (int j = 0;j < 9 - i;j++)
{
if (parr[j] > parr[j + 1])
{
int temp = parr[j + 1];
parr[j + 1] = parr[j];
parr[j] = temp;
flag = 1; // 交换了就赋值
}
}
if (!flag)
{
// 如果有一轮没发生交换 就说明已经排序完成了 提前跳出循环
break;
}
}

for (int i = 0;i < 10;i++)
{
printf("%d ", arr[i]);
}