文章目录
- 1.字符指针:
- 2.数组指针:
- 3.二维数组传参的本质
- 4.函数指针变量
- typedef 关键字
- 5.函数指针数组
- 6.转移表
1.字符指针:
字符指针,也称为字符串指针,是指向内存中的字符或字符串的指针。
在C语言中,字符串被表示为以空字符 '\0'
结尾的字符数组。
#include <stdio.h>int main()
{// 字符指针的声明和初始化char *str = "Hello, bit!";// 使用字符指针打印字符串printf("字符串: %s\n", str);// 使用指针算术运算访问单个字符printf("第一个字符: %c\n", *str);printf("第二个字符: %c\n", *(str + 1));return 0;
}
解释:
- 我们声明一个字符指针
str
并将其初始化为字符串"Hello, bit!"
。本质是把字符串hello world
的首地址放到了str
中。 - 然后使用
%s
格式说明符打印整个字符串。 - 使用指针算术运算,我们访问并打印字符串的单个字符。
来看一道字符串相关的笔试题 ——from《剑指offer》
#include <stdio.h>
int main()
{char str1[] = "hello bit";char str2[] = "hello bit";const char* str3 = "hello bit";const char* str4 = "hello bit";if (str1 == str2)printf("str1 and str2 are same\n");elseprintf("str1 and str2 are not same\n");if (str3 == str4)printf("str3 and str4 are same\n");elseprintf("str3 and str4 are not same\n");return 0;
}
2.数组指针:
数组指针变量应该是:存放的应该是数组的地址,能够指向数组的指针变量
int *p1[10];
//p是一个指针变量数组(数组的元素类型都是指针),指针指向整型数组
int (*p2)[10];
//p是一个指针变量,然后指向的是大小为10的整型数组
//(数组元素10个,每个元素类型是int)
[]
的优先级是要高于*
的,所以必须加上( )
来保证p
和*
先结合
#include <stdio.h>int main()
{// 声明并初始化整型数组int arr[] = {1, 2, 3, 4, 5};// 声明一个数组指针int *ptr;// 使用数组的基地址初始化数组指针ptr = arr;// 使用数组指针访问数组元素printf("数组元素: ");for (int i = 0; i < 5; i++){printf("%d ", *(ptr + i));}printf("\n");return 0;
}
运行结果
#include <stdio.h>int main()
{// 声明并初始化整型数组int arr[5] = { 1, 2, 3, 4, 5 };// 声明一个数组指针int (*ptr)[5]=&arr;//得到的是数组地址return 0;
}
解释:
- 我们声明一个整型数组
arr
并将其初始化为一些值。 - 我们声明一个数组指针
ptr
。 - 使用数组
arr
的基地址初始化数组指针ptr
。 - 使用指针算术,我们访问并打印数组的元素。
字符指针和数组指针的区别:
-
数据类型:
- 字符指针(
char *
)用于指向字符或字符串。 - 数组指针(
int *
、float *
等)用于指向数组的第一个元素。
- 字符指针(
-
用途:
- 字符指针通常用于字符串的操作和处理。
- 数组指针用于高效访问数组的元素。
3.二维数组传参的本质
先看不用指针怎么实现二维数组的传参
#include <stdio.h>
void test(int a[3][5], int r, int c)
{int i = 0;int j = 0;for (i = 0; i < r; i++){for (j = 0; j < c;j++){printf("%d " , a[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} };test(arr, 3, 5);return 0;
}
这里实参是二维数组,形参也可以写出二维数组
那么用指针怎么写捏
首先我们要明确,二维数组名表示的是第一行的地址
我们可以知道一维数组的类型是int[5]
,所以第一行第地址数组类型就是int(*)[5]
那就意味着二维数组传参的本质是传递了地址,传递的是这个一维数组的地址
所以我们可以这么写
#include <stdio.h>
void test(int *p [5], int r, int c)
{int i = 0;int j = 0;for (i = 0; i < r; i++){for (j = 0; j < c;j++){printf("%d " , *(*(p+i)+j));//*(p+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} };test(arr, 3, 5);return 0;
}
总结:二维数组传参,形参可以写成数组,也可以写成指针
4.函数指针变量
先看一段代码
#include<stdio.h>
void test()
{printf("hehe\n");
}
int main()
{printf("test: %p\n", test);printf("&test: %p\n", &test);return 0;
}
所以为了存放函数地址,就有了函数指针变量
void test()
{printf("hehe\n");
}
void(*pf1)() = &test;
void (*pf2)() = test;int Add(int x, int y)
{return x + y;
}
void(*pf3)(int, int) = Add;
void(*pf4)(int x, int y) = &Add;//x和y写上和省略都是可以的
一个例子
#include <stdio.h>
int Add(int x, int y)
{return x + y;
}
int main()
{int (*pf3)(int, int) = Add;printf("%d\n", (*pf3)(2,3));printf("%d\n", pf3(3, 5));return 0;
}
两段有趣 的代码
都出自《c陷阱和缺陷》
typedef 关键字
如果是指针类型,能否重命名呢?其实也是可以的,⽐如,将int*
重命名为 ptr_t
,这样写:
但是对于数组指针和函数指针稍微有点区别:
⽐如我们有数组指针类型int(*)[5]
,需要重命名为parr_t
,那可以这样写
新类型名 要在*
右边
函数指针类型的重命名也是⼀样的,⽐如,将 void(*)(int)
类型重命名为 pf_t
,就可以这样写:
上面第二段有趣代码的简化
5.函数指针数组
以下哪个会是正确写法呢
答案是:parr1
parr1
先和 []
结合,说明 parr1
是数组,数组的内容是什么呢?
是 int (*)()
类型的函数指针。
6.转移表
函数指针用途:转移表
举例:计算器的一般实现
#include <stdio.h>int add(int a, int b)
{return a + b;
}sub(int a, int b)
{return a - b;
}int mul(int a, int b)
{return a * b;
}int div(int a, int b)
{return a / b;
}int main() {int ret = 0;int input= 1;int X, Y;do{printf("1:add 2:sub 3:mul 4:div 0:exit\n");scanf("%d", &input);printf("Enter the value of X: ");scanf("%d", &X);printf("Enter the value of Y: ");scanf("%d", &Y);switch (input) {case 1:ret = add(X, Y);break;case 2:ret = sub(X, Y);break;case 3:ret = mul(X, Y);break;case 4:ret = div(X, Y);break;case 0:printf("退出程序\n");break;default:printf("Invalid option");break;}printf("%d\n", ret);}while(input);return 0;
}
使用函数指针数组来实现
#include <stdio.h>int add(int a, int b)
{return a + b;
}sub(int a, int b)
{return a - b;
}int mul(int a, int b)
{return a * b;
}int div(int a, int b)
{return a / b;
}int main() {int ret = 0;int input = 1;int x, y;int(*p[5])(int x, int y) = { 0,add,sub,mul,div };do{printf("1:add 2:sub 3:mul 4:div 0:exit\n");scanf("%d", &input);if ((input <= 4 && input >= 1)){printf("请输入操作数\n");scanf("%d %d", &x, &y);ret = (*p[input])(x, y);printf("ret = %d\n", ret);}else if (input == 0){printf("退出计算机\n");}else{printf("输入有误\n");}}while(input);return 0;
}
未完待续…