前言
本章主要讲解数组名用法,二级指针及指针数组
在使用数组名时,很多时候数组名表示首元素地址,但也有特例。
以下是数组名表示整个数组的用法
- 在使用操作符sizeof时
int arr[]={1,2,3,4,5,6,7,8,9};
int sz=sizeof(arr)/sizeof(arr[0]);//求数组长度(数组元素个数),sz=9,在这里arr就表示整个数组
2.在使用取地址符号&时
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("arr = %p\n", arr);
printf("arr+1 = %p\n", arr+1);
printf("&arr = %p\n", &arr);
printf("&arr+1 = %p\n", &arr+1)
结果如图所示(16进制地址)
arr代表首地址,所以arr+1后地址+4,&arr代表整个数组,加+1后,地址+4*数组大小
#include
int main(){
int arr[] = {1,2,3,4,5,6};
int i = 0;
int sz = sizeof(arr)/sizeof(arr[0]);//计算数组长度
int* p = arr;//指针p指向arr数组首元素
for(i=0; i<sz; i++){
printf("%d ", *(p+i));//实际上*(p+i)=p[i],就像数组一样
}
return 0;
}
实际上*(p+i)=p[i],同理arr[i] 应该等价于 *(arr+i),数组元素的访问在编译器处理的时候,也是转换成⾸元素的地址+偏移量求出元素的地址,然后解引⽤来访问的。
二级指针是指向指针的指针。
int a = 10;
int *p = &a; // p 是一个指向 int 类型的指针,存储了变量 a 的地址
int **pp = &p; // pp 是一个指向 int* 类型的指针,存储了指针 p 的地址
指针数组和数组指针经常会被混淆,分清它们是很重要的。
指针数组是一个数组,其中的每个元素都是指针。
int num1 = 10;
int num2 = 20;
int num3 = 30;
int* arr[3]={ &num1 , &num2 , &num3 }; // 声明一个指针数组,数组元素是指向 int 的指针
printf("Value at arr[0]: %d\n", *arr[0]); // 输出 num1 的值
printf("Value at arr[1]: %d\n", *arr[1]); // 输出 num2 的值
printf("Value at arr[2]: %d\n", *arr[2]); // 输出 num3 的值
数组指针是一个指针,它指向一个数组。数组指针可以用于指向一维或多维数组。数组指针的类型与所指向数组的类型有关。
int (*arr)[3] = {10, 20, 30};
//[]优先级比*高,*arr加括号再与[],或者这种写法
int *arr[3] = {10, 20, 30}; // 声明一个指向 int 的指针,指向数组 arr 的第一个元素
int *ptr = arr;//在这个示例中,ptr 是一个指向整数的指针,它指向数组 arr 的第一个元素。你可以通过递增指针来遍历数组中的元素。
指针和二维数组的关系: 一个指向二维数组的指针实际上是一个指向一维数组的指针。这是因为在内存中,二维数组的行在连续的内存位置上,因此可以通过一个指向一维数组的指针来访问不同的行。
例如,考虑以下的二维数组和指针:
int arr[3][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
int(*ptr)[3] = arr; // 指向二维数组arr的第一行
int i = 0;
for (i = 0; i < 3; i++) {
int j = 0;
for (j = 0; j < 3; j++) {
printf("%d ", ptr[i][j]);//等价于printf("%d ",*(*(ptr+i)+j));
}
printf("\n");
}
函数在内存中也有一个地址,这个地址标识了函数在程序中的位置,允许程序能够通过地址来调用函数。函数的地址实际上是指向函数代码所在内存位置的指针,也被称为函数指针。
#include
int Add(int x, int y) {
return x + y;
}
int main() {
int x = 5;
int y = 6;
int ret=Add(x,y);
printf("%p\n",Add);//函数名本身就是地址,可以不使用取地址符号
printf("%p", &Add);
return 0;
}
运行结果:
既然是有地址的,我们就可以创建指针将其地址存起来。
函数指针的语法如下:
//其中,return_type 是函数的返回类型,function_pointer_name 是函数指针的名称,parameter_list 是函数的参数列表。
return_type (*function_pointer_name)(parameter_list);
实例:
#include
// 函数原型
int add(int a, int b) {
return a + b;
}
int subtract(int a, int b) {
return a - b;
}
int main() {
// 声明函数指针,指向带有两个 int 参数并返回 int 的函数
int (*pf)(int, int);
// 赋值函数指针,使其指向 add 函数
pf = add;
// 使用函数指针调用函数
int result = pf(5, 3);
printf("Result: %d\n", result); // 输出:Result: 8
// 改变函数指针的指向,使其指向 subtract 函数
pf = subtract;
result = pf(10, 4);
printf("Result: %d\n", result); // 输出:Result: 6
return 0;
}
在示例中,我们声明了一个函数指针 pf,使其可以指向带有两个 int 参数并返回 int 的函数。然后,我们赋值给这个函数指针,使其分别指向 add 函数和 subtract 函数。通过函数指针,我们可以调用不同的函数,实现了在运行时动态选择调用的函数。
typedef 是中的一个关键字,用于定义新的数据类型名称。它可以用来为已有的数据类型(如基本数据类型、结构体、指针等)创建别名,以便更方便地使用这些类型。
typedef 的语法形式如下:
//existing_data_type 是已有的数据类型,new_data_type_name 是你为其创建的新类型名称
typedef existing_data_type new_data_type_name;
为函数指针类型创建别名:
typedef int (*pfun_t)(int, int); // 将函数指针类型[int (*)(int, int)]定义为 pfun_t 类型的别名
pfun_t funcPtr = add; // 使用 pfun_t 类型来声明函数指针变量,funcPtr是函数指针变量名
函数指针数组是一个数组,其元素都是函数指针。这意味着每个数组元素存储了一个指向特定函数的地址,使得可以通过数组来调用不同的函数。
以下是创建和使用函数指针数组的一般步骤:
typedef int (*pfun_t)(int, int); // 定义 pfun_t 为函数指针类型
int main() {
pfun_t arr[3]; // 声明函数指针数组,数组元素为 pfun_t 类型的函数指针
// 可以将不同函数的地址赋值给数组元素
arr[0] = add;
arr[1] = subtract;
// ...
// 使用函数指针数组调用函数
int result = arr[0](5, 3); // 调用 add 函数
printf("Result: %d\n", result);
// ...
return 0;
}
转移表(也称为查找表、跳转表、分支表)是一种在编程中用于优化条件分支操作的技术。它通常用于替代一系列的 if-else 或 switch 语句,从而提高代码的执行效率和可读性。
计算器的⼀般实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include
int add(int a, int b){
return a + b;
}
int 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 x, y;
int input = 1;
int ret = 0;
int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表
do{
printf("*************************\n");
printf("****** 1:add 2:sub ****** \n");
printf("****** 3:mul 4:div ******\n");
printf("******** 0:exit *********\n");
printf("*************************\n");
printf("请选择:");
scanf("%d", &input);
if ((input <= 4 && input >= 1)){//选择计算方式
printf("输入操作数:");
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;
}