目录
数组名的理解
使用指针访问数组
为什么指针能访问数组?
一维数组传参的本质
冒泡排序(升序)
二级指针
指针数组
指针数组模拟二维数组
数组名的理解
数组名是数组首元素地址
例外:数组名只在以下两个情况下代表整个数组
1. &数组名:整个数组的地址
2. sizeof(数组名):计算的是整个数组的大小
指针类型决定了指针的差异
使用指针访问数组
arr[i] 编译器会自动转化成指针方式读取,所以这里的[ ]只是一个操作符
为什么指针能访问数组?
1.数组在内存中是连续存放的
2.指针的运算很方便,可以很方便的遍历数组
一维数组传参的本质
实参传递的是首元素的地址,因为在主函数里面调用子函数时,用f(arr);
形参可以写成数组形式,但本质上都是指针的形式
只能在主函数里算出数组的元素个数,再传到子函数里
冒泡排序(升序)
思路:
10个元素要进行9趟的比较,n个就比较n-1次
第一个元素不变,其他元素和他进行比较,利用嵌套循环
因为每比较完一趟,就少一个数字参与比较,所以内循环要变化,就是 j < n - 1 - i 趟
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> void scan(int* arr, int sz) { for (int i = 0; i < sz; i++) { scanf("%d", arr+i); } } void bubble_sort(int* arr, int sz) { for (int i = 0; i < sz - 1; i++) { // i表示趟数 for (int j = 0; j < sz - 1 - i;j++) { //j表示内部的比较,每一趟少i次的比较 if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } void print(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]); scan(arr, sz); bubble_sort(arr, sz); print(arr, sz); return 0; }优化:利用flag
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> void scan(int* arr, int sz) { for (int i = 0; i < sz; i++) { scanf("%d", arr+i); } } void bubble_sort(int* arr, int sz) { for (int i = 0; i < sz - 1; i++) { int flag = 1; //假设已经满足顺序 for (int j = 0; j < sz - 1 - i;j++) { if (arr[j] > arr[j + 1]) { flag = 0; int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } if (flag == 1) { break; } } } void print(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]); scan(arr, sz); bubble_sort(arr, sz); print(arr, sz); return 0; }二级指针
int main(){ int a = 10; int * p = &a; //一级指针 int ** ppa = &pa; //二级指针 }ppa指向的pa的类型是int *
二级指针用来存放一级指针变量的地址
**ppa == *pa == pa
二级指针和二维数组没有对应关系
指针数组
存放指针的数组,数组中的每个元素是指针类型
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> int main() { int a = 1; int b = 2; int c = 3; int* arr[3] = { &a,&b,&c }; for (int i = 0; i < 3; i++) { printf("%d ", *(arr[i])); } return 0; }指针数组模拟二维数组
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> int main() { int arr1[5] = { 1,2,3,4,5 }; int arr2[5] = { 6,7,8,9,0 }; int arr3[5] = { 4,5,6,7,8 }; int* arr[3] = {arr1,arr2,arr3 }; for (int i = 0; i < 3; i++) { for (int j = 0; i < 5; j++) { printf("%d ", arr[i][j]); } } return 0; }字符指针变量
写法一
char ch = 'w';
char * pa = &pc;
*pc = 'b';
printf("%c\n",*pc);
写法二
常量字符串会放在只读数据区
const char *p = "abcdef"; //这里的赋值是将字符串中的首字符的地址赋值给p
char *p = arr;
数组指针
指针数组是 int * arr[5]
字符指针:char* pc
整型指针:int * pa
数组指针???
数组指针:指向数组的指针,存放数组的地址
总结:1.指针 2.是一个指向数组的指针
int arr[5] = { 1,2,3,4,5 };
int *p = arr; //这里的p是整型指针变量,指向数组首元素的地址
int (*p) [5] = &arr; //这里的p是数组指针,p存放的是数组的地址
//p的类型是int (*) [5] ,等号右边&arr的类型也是这个
int arr[5];
int (*p)[5] = &arr;
二维数组传参的本质
int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}};
二维数组的数组名也表示首地址
首地址是二维数组的第一行
第一行是一维数组
二维数组传参,本质上是传递了第一行这个一维数组的地址
所以二维数组 传的形参,用数组指针,表示指向这个二维数组的首地址
写一个打印二维数组的函数
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> //写一个打印二维数组的函数 void Print(int(*arr)[5], int r, int c) { for (int i = 0; i < r; i++) { for (int j = 0; j < c; j++) { printf("%d ", (*(*(arr + i))+j)); //printf("%d ", (*(arr + i))[j]); } printf("\n"); } } int main() { int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} }; Print(arr, 3, 5); return 0; }思路:要怎么才能取出二维数组中的每个元素?
1. 取出二维数组中第i行第j列的元素
2. 要找到第i行第j列的地址
3. 得找到第i行的首地址
4. 那得先找到第i行的这个行地址
知道这些然后再进行倒退,
我们知道数组名arr是二维数组的首地址
4. 那么第i行的这个行地址就是arr+i,它指向的是一整行
二维数组中,每个一维数组的地址如图
3. 再找到第i行的首地址,用*(arr+i)表示,它指向的是 i 行第 0 个元素的地址,但它只知道这一个 格子,只指向这第一个元素
2. 想让它指向下一个元素的地址,用*(arr+i)+j 表示第 i 行第 j 个元素的地址
1. 最后取出第i行第j列的元素的值,*(*(arr + i))+j