一、数组名的理解
数组名是数组首元素的地址,但有两种例外情况。
例外情况① sizeof(数组名)
sizeof中单独放数组名,这里的数组名表示整个数组,求的是整个数组的大小,单位是字节。
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
printf("%zd\n", sizeof(arr));//这里的数组名如果理解为数组首元素的地址的话,那么在64位环境下应该是8个字节,在32位环境下应该是4个字节
//但输出的结果却是40个字节,显然理解有误。
//其实这里求的是整个数组所占内存空间的大小
printf("%zd\n", sizeof(arr + 0));//这里sizeof中不是单独放的数组名,而是arr+0,这里的arr+0应该理解为数组首元素的地址。
//那么在64位环境下应该是8个字节,在32位环境下应该是4个字节
}
例外情况②&数组名
这里的数组名也表示整个数组,取出的是整个数组的地址。注意,整个数组的地址与数组首元素的地址是不一样的。
因为&arr[0]与arr都是int * 类型的地址,故&arr[0]+1与arr+1都是跳过一个int类型的长度。&arr表示取出整个数组的地址,则&arr+1表示跳过整个数组。
二、使用指针访问数组
int main()
{
int arr[10] = { 0 };
int sz = sizeof(arr) / sizeof(arr[0]);
//输入
for (int i = 0; i < sz; i++)
{
scanf("%d", arr+i);//arr+i表示下标为i元素的地址
}
//输出
for (int i = 0; i < sz; i++)
{
printf("%d ", *(arr + i));
//printf("%d ", *(i + arr));
//printf("%d ", arr[i]);
//printf("%d ", i[arr]);
}
return 0;
}
总结: ①arr+i与i+arr均表示arr数组中下标为i元素的地址 。
② arr[i]与i[arr]与*(arr+i)与*(i+arr)均表示arr数组中下标为i的元素。
三、一维数组传参的本质
①数组传参时,实参写数组名,形参既可以写成数组的形式,也可以写成指针的形式。形参无论写成哪种形式,本质上传递的还是数组首元素的地址。并且形参的数组和实参多数组是同一个数组。
②形参写成数组形式的好处:对于没有学过指针的初学者而言,更容易上手数组。
③一维数组传参时,形参若写成一维数组时,数组的大小可以省略;二维数组传参时,形参若写成二维数组时,二维数组行的大小可以省略,列的大小不能省略。
四、冒泡排序
例如将n个乱序的整数排成升序,需要进行n-1趟排序,每一趟解决一个元素
Input(int* arr, int sz)
{
for (int i = 0; i < sz; i++)
{
scanf("%d", arr + i);
}
}
void bubble_sort(int* arr, int sz)
{
/*数组中有sz个元素,需要进行sz - 1趟冒泡排序,每一趟解决一个元素。因此外循环要循环sz-1次*/
for (int i = 0; i < sz - 1; i++)
{
/*
第一趟冒泡排序需要将sz-1对元素两两比较,第一趟冒泡排序结束后,最大的元素就排好位置了
第二趟冒泡排序需要将sz-2对元素两两比较,第二趟冒泡排序结束后,第二大的元素就排好位置了
第三趟冒泡排序需要将sz-3对元素两两比较,第三趟冒泡排序结束后,第三大的元素就排好位置了
依次类推
*/
for (int j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int temp = 0;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
void Ouput(int* arr, int sz)
{
for (int i = 0; i < sz; i++)
{
printf("%d ", *(arr + i));
}
}
int main()
{
int arr[10] = { 0 };
int sz = sizeof(arr) / sizeof(arr[0]);
//输入
Input(arr, sz);
//将数组中的元素排成升序
bubble_sort(arr, sz);
//输出
Ouput(arr, sz);
return 0;
}
以上的冒泡排序算法(bubble_sort函数)在某种情况下,运行时会特别浪费时间。比如arr数组中的元素本来就满足升序时,bubble_sort函数依旧会进行sz-1趟冒泡排序,但显然这比较浪费时间。下面对bubble_sort函数进行优化,优化目的:当arr数组中的元素本来就满足升序时,只需要进行一趟冒泡排序。
void bubble_sort(int* arr, int sz)
{
/*数组中有sz个元素,需要进行sz - 1趟冒泡排序,每一趟解决一个元素。因此外循环要循环sz-1次*/
for (int i = 0; i < sz - 1; i++)
{
/*
第一趟冒泡排序需要将sz-1对元素两两比较
第二趟冒泡排序需要将sz-2对元素两两比较
第三趟冒泡排序需要将sz-3对元素两两比较
依次类推
*/
int flag = 1;//假设arr数组中的元素已经满足升序
for (int j = 0; j < sz - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
flag = 0;
int temp = 0;
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
if (flag == 1)
{
break;
}
}
}