C语言第15讲
数组名的理解
数组名就是首元素地址
但又两个例外:
1.sizeof(arr)
2.&arr
这两个数组名都表示整个数组
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>int main()
{int arr[10] = { 0 };printf("%d\n", sizeof(arr));printf("%p\n", &arr);printf("%p\n", &arr+1);return 0;
}
[ ] 的详细理解
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9 };int sz = sizeof(arr) / sizeof(arr[0]);int* p = arr;for (int i = 0; i < sz; i++){printf("%d ", *(p + i));printf("%d ", *(i + p));printf("%d ", p[i]);printf("%d ", arr[i]);printf("%d ", *(arr + i));printf("%d ", *(i + arr));printf("%d ", i[p]);printf("%d ", i[arr]);printf("\n");}return 0;
}
a + b = b + a +是操作符
[ ] 也是操作符 p[ i ] = i[ p ]
因为 arr[ i ] 在计算机中会翻译成 *(arr + i)
且 p 和 arr 都是首元素地址,所以以上所有表达式都是一样的意思
一维数组传参的本质
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>void print(int arr[], int sz)
{for (int i = 0; i < sz; i++)printf("%d ", *(p + i));
}int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9 };int sz = sizeof(arr) / sizeof(arr[0]);print(arr, sz);return 0;
}
以上代码我们将 sz 转移至函数内部计算会发生什么?
在内部计算:sz = 1
因为函数在传一维数组时,传的是首元素地址,放入函数内部计算时
sizeof(arr) / sizeof(arr[0])
会被翻译为 指针变量 / 首元素大小 ,x86 = 1,x64 = 2
数组传参的时候,形参可以写成数组的形式 int arr[ ],但本质还是指针变量
冒泡排序
核心思想:两两相邻元素进行比较
例:将 1 2 3 4 5 6 7 8 9 改为降序
冒泡排序每一趟解决一个数的排序
第一趟:需要进行 n(总元素个数) - 1次比较
第二趟:由于第一趟已经解决一个数的排序,所以比较此次会再次减少一次
每趟解决一个数据,最后一趟解决2个数据,所以需要总趟数 n(总元素个数) - 1趟次
所以比较次数的写法:
for (int i = 0; i < sz - 1; i++)
{for (int j = 0; j < sz - 1 - i; j++){}
}
且每趟比较完,下趟数据得从头开始比较,所以 j = 0; 为比较顺序的重置
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>void bubble_sort(int* p, int sz)
{for (int i = 0; i < sz - 1; i++){int flag = 1;for (int j = 0; j < sz - 1 - i; j++){if (p[j] > p[j + 1]){int tmp = p[j];p[j] = p[j + 1];p[j + 1] = tmp;flag = 0;}}if (flag == 1){break;}}
}void print(int* p, int sz)
{for (int i = 0; i < sz; i++){printf("%d ", p[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);print(arr,sz);return 0;
}
bubble_sort 函数内的 flag 为冒泡排序的优化,如果一趟中,没发生位置的交换,说明已经排序完成,后续趟数的比较,不用再进行,直接跳出循环
二级指针
int a = 10;
int* p = &a;
int** pp = &p;
pp就是二级指针,将一级指针的地址存入另一个变量中,这个变量就是二级指针
int* (*) 表示pp是指针变量
(int*) * 表示pp指向的对象为指针变量
和一级指针一样:直接使用pp
printf("%p",*pp);
printf("%d",*(*pp));
*pp+1 意思是 p的指针加一个int *的内存
x86,p的地址加4
x64,p的地址加8
并不是a的地址
*pp分两类,可以利用 printf %d 打印内容 %p打印地址
指针数组
(谁在后面,谁是名称)指针数组就是数组
字符数组:存放字符的数组
整形数组:存放整形的数组
字符数组:存放指针的数组
书写:int*(元素类型) arr[ ];
指针数组模拟二维数组
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>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[] = { arr1,arr2,arr3 };//使用直接利用二维数组方式for (int i = 0; i < 3; i++) {for (int j = 0; j < 5; j++){printf("%d ", arr[i][j]);}printf("\n");}return 0;
}