1.字符指针
一般的使用
通过字符指针 char*p 将字符 ch 的内容由 m 改写为 y
另一种使用
其本质就是将字符串“abcdef",首字符的地址存放在字符指针 p 中
经典例题
#include<stdio.h> int main() { char ch1[] = "abcdef"; char ch2[] = "abcdef"; const char* ch3 = "abcdef"; const char* ch4 = "abcdef"; if (ch1 == ch2) { printf("ch1 and ch2 are same\n"); } else printf("ch1 and ch2 are not same\n"); if (ch3 == ch4) { printf("ch3 and ch4 are same\n"); } else printf("ch3 and ch4 are not same\n"); return 0; }
运行结果如下
ch3,ch4指向同一字符串,指向同一块内存。所以相同
ch1,ch2 由于是相同的常量字符串初始化不同的数组,便会开辟不同的内存块,所有不同
2.指针数组
int*arr1[10];//整形指针的数组 char*arr2[10];//字符指针的数组 char**arr3[10];//二级字符指针的数组
3.数组指针
3.1数组指针的诠释
数组指针,顾名思义是指针,前面加上个数组,所i有数组指针就是指向数组的指针
int(*p)[10]; p 的类型是 int(*)[10] p 指向一个整形数组,数组有10个元素 int [10]
3.2 &数组名vs数组名
数组名通常表示的都是数组首元素地址 只有两个例外 1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小 2.&数组名,这里的数组名表示的依然是整个数组,所以&数组名取出的是整个数组的地址
观察下列代码
#include<stdio.h> int main() { int arr[10] = { 0 }; printf("%p\n",arr); printf("%p\n", &arr); return 0; }
运行结果如下
由此可见数组名,&数组名打印的地址是一样的,但真是如此吗?????
再观察一段代码
#include<stdio.h> int main() { int arr[10] = { 0 }; printf("%p\n", arr); printf("%p\n", &arr); printf("arr+1=%p\n", arr + 1); printf("&arr+1=%p\n", &arr + 1); return 0; }
由运行结果可以知道,&arr,arr,虽然再数值上是一样的,但本质上是不同的。
实际上:&arr表示的是整个数组的地址。
整个数组的地址+1,跳过整个数组。
3.3 数组指针的使用
既然数组指针指向的是数组,所以数组指针中存放的是数组的地址。
数组指针的使用-> 模拟二维数组
#include<stdio.h> void Print(int(*p)[3], int row, int col) { int i = 0;//先按行打印 for (i = 0; i < row; i++) { int j = 0;//打印每行中的数据 for (j = 0; j < col; j++) { printf("%d ", p[i][j]); } printf("\n");//打印完一行之后需要换行 } } int main() { int arr[3][3] = { 1,2,3,2,3,4,3,4,5 }; Print(arr, 3, 3); //数组名表示首元素地址 //二维数组的首元素是二位数组的第一行 //这里的arr,相当于第一行的地址,一个一维数组的地址 //数组的地址,当然需要用数组指针来接受 return 0; }
4.数组传参,指针传参
4.1一维数组传参
//数组传参可以传数组本身,亦可以传指针 void test1(int arr1[]) {} void test1(int arr1[10]) {} void test1(int *arr) {} void test2(int *arr2[10]) {} //指针数组,元素类型是int*, 数组名是首元素地址,需要指针来接收 //所以形参可以是二级指针 void test2(int **arr2) {} int main() { int arr1[10] = { 0 }; int* arr2[10] = { 0 }; test1(arr1); test2(arr2); return 0; }
4.2二维数组传参
#include<stdio.h> //形参的二维数组行可省略,列不可省略 void test(int arr[3][4]) {} void test(int arr[][4]) {} //二维数组的数组名,表示首元素地址 //就是第一行的地址,第一行地址是一个一维数组的地址 //可以用数组指针来接收 void test(int(*arr)[4]) {} int main() { int arr[3][4] = { 0 }; test(arr); return 0; }
4.3一级指针传参
void Print(int* parr, int sz) { int i = 0; for (i = 0; i < sz; i++) { printf("%d ", parr[i]); } } int main() { int arr[] = { 1,2,3,4,5,6,7,8,9 }; int* parr = arr; int sz = sizeof(arr) / sizeof(arr[0]); //一级指针传给函数 Print(parr, sz); return 0; }
如果函数的形参是指针,实参有哪些可能呢
void Print(int*p) {} int main() { int a = 10; int* p = &a; int arr[10] = { 0 }; Print(&a);//直接取出整形a的地址 Print(p);//将整形a的地址存放在指针p中 Print(arr);//数组名是首元素地址 return 0; }
4.4 二级指针传参
void test(int** ptr) {} int main() { int a = 10; int* p = &a; int** pp = &p; test(pp);//直接将二级指针作为实参 test(&p);//取出一级指针的地址作为实参 return 0; }
如果函数的形参是二级指针,实参有哪些可能呢
void test(int**p) {} int main() { int a = 10; int* p = &a; int** pp = &p; int* arr[10] = { 0 }; //指针数组,数组名是首元素地址,首元素类型是int* test(&p); test(pp); test(arr); return 0; }
5.函数指针
函数指针,顾名思义是指针,指向函数的指针。
int(*pf)(int,int) 函数指针,指向的函数返回类型是int,参数是(int,int)
int Add(int x, int y) { return x + y; } int main() { int arr[10] = { 0 }; //&数组名,取出数组的地址 int(*p)[10] = &arr;//数组指针 //&函数名,取出的就是函数的地址 int(*p)(int, int) = &Add;//函数指针 return 0; }
对于函数来说,&函数名和函数名都是函数的地址。
函数指针实现计算器(不包含浮点数)
#include<stdio.h> void menu() { printf("**********************\n"); printf("*****1.Add 2.Sub ****\n"); printf("*****3.Mul 4.Div ****\n"); printf("********0.exit *******\n"); printf("**********************\n"); } int Add(int x, int y) { return x + y; } int Sub(int x, int y) { return x - y; } int Mul(int x, int y) { return x * y; } int Div(int x, int y) { return x / y; } void calc(int(*pf)(int, int)) { int x = 0; int y = 0; printf("请输入两个操作数>"); scanf("%d%d", &x, &y); int ret = pf(x, y); printf("%d\n", ret); } int main() { int input = 1; do { menu(); printf("请选择>"); scanf("%d", &input); switch (input) { case 1: calc(Add); break; case 2: calc(Sub); break; case 3: calc(Mul); break; case 4: calc(Div); break; case 0: printf("退出计算器\n"); break; default: printf("选择错误\n"); break; } } while (input); return 0; }