函数指针数组的小尝试

本文介绍了函数指针的概念及函数指针数组的使用方法,通过一个计算器程序展示了如何使用函数指针数组简化代码,避免使用复杂的分支结构。

首先,认识一下函数指针
void (prt)(int x, int y)
这就是一个很简单的函数指针,prt先和解引用操作符结合说明这是一个指针,后面跟调用操作符()表示这个指针指向一个函数,函数的参数是两个int 型,返回一个void。
函数指针数组,就是一个存放函数指针的数组。
int ( * prt[10])(int x, int y)
prt先和[]结合说明它是一个数组,它存储的是int (
)(int x, int y)型的函数指针。
下面简单的编写一个计算器程序来展示一下函数指针数组的用法:
普通的方法应该是这样的,利用分支来选择要执行的操作

#include<stdio.h>
#include<stdlib.h>

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;
	while (input)
	{
		printf("******************************\n");
		printf("      1.add             2.sub\n");
		printf("      3.mul             4.div\n");
		printf("      0.exit                 \n");
		printf("******************************\n");
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("输入操作数:");
			scanf("%d%d", &x, &y);
			ret = Add(x, y);
			break;
		case 2:
			printf("输入操作数:");
			scanf("%d%d", &x, &y);
			ret = Sub(x, y);
			break;
		case 3:
			printf("输入操作数:");
			scanf("%d%d", &x, &y);
			ret = Mul(x, y);
			break;
		case 4:
			printf("输入操作数:");
			scanf("%d%d", &x, &y);
			ret = Div(x, y);
			break;
		case 0:
			printf("退出游戏!");
			break;
		default:
			printf("输入错误\n");
			break;
		}
		printf("ret = %d\n", ret);
	}
	return 0;
}

如果使用了函数指针,那main函数就能简化很多,子函数不变,在主函数中定义一个函数指针数组来存储函数地址。

int main()
{
	int x, y;
	int input = 1;
	int ret = 0;
	int (*p[5])(int x, int y) = { 0, Add, Sub, Mul, Div };
	while (input)
	{
		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);
		}
		else
		{
			printf("输入有误");
		}
		printf("ret = %d\n", ret);
	}
	return 0;
}

<think>嗯,用户想了解C/C++中数组名和指针的区别。好的,这个问题我之前学过,但可能有些细节需要回忆一下。首先,我记得数组名在大多数情况下会被编译器转换为指向数组首元素的指针,但数组名本身并不是指针变量,而是一个常量指针。对吗? 根据引用内容,比如引用[1]提到,数组名会被编译器自动替换为指向首元素的指针,比如int arr[]的情况下,arr会被当作&arr[0]。所以当输出arr和p的时候,地址是一样的。这说明数组名和指针在某些情况下行为相似。但引用[3]里提到数组指针指向整个数组的地址,而数组名可能更接近首元素的地址?这里需要区分数组指针指针数组的不同。 然后,数组名是常量,不能被重新赋值,而指针是变量,可以指向其他地址。例如,像arr = another_array;这样的操作是非法的,而指针p可以指向其他地方。这点应该正确,用户可能需要知道这一点区别。 还有sizeof操作符的结果不同。对于数组名,sizeof返回整个数组的大小,而指针的话则是指针本身的大小,比如在64位系统上是8字节。引用中可能没有直接提到这点,但根据常识,这是关键区别之一。 另外,取地址操作符&的结果不同。对数组名使用&,得到的是整个数组指针,类型是数组指针(比如int (*)[n]),而对指针变量使用&,得到的是指针变量的地址,类型是int**。引用[3]提到数组指针需要解引用才能访问元素,所以这部分可能相关。 类型信息方面,数组名保留了数组的类型和长度信息,而指针只保存地址。例如,当传递数组名给函数时,它退化成指针函数内部无法知道数组的长度,这也是为什么需要传递长度参数的原因。引用[5]中的例子显示,使用数组指针传递到函数时,可能需要解引用才能正确访问元素。 还有,数组名作为函数参数时会退化为指针。比如在函数参数中声明int arr[]其实等同于int* arr。这点引用中可能提到过,比如引用[1]中的编译器自动替换。 总结起来,数组名和指针的区别主要有:是否为常量、sizeof结果、&操作的结果、类型信息保留情况、以及作为函数参数时的退化行为。需要将这些点整理清楚,用例子说明,比如代码示例中的sizeof差异,或者尝试修改数组名的地址导致编译错误的情况。 可能还需要提到指针数组数组指针的区别,但用户的问题主要是数组名和指针的关系,所以这部分可能稍微带过。引用[5]中的例子展示了数组指针的使用,可以用来解释数组名和指针的不同使用场景。 用户可能在实际编程中遇到数组名被当作指针使用的情况,但需要理解背后的原理,比如为什么不能对数组名进行赋值,或者为什么传递数组函数后长度信息丢失。这些实际应用中的问题都需要在回答中覆盖。 最后,要确保引用的内容正确对应到各个区别点,比如引用[1]说明数组名被替换为指针,引用[3]说明数组指针的解引用方式,引用[5]中的代码示例展示数组指针的使用方法。结合这些引用内容,组织一个结构清晰的回答,分点列出区别,并给出代码示例和注意事项。</think>### 数组名与指针的区别(C/C++) 在C/C++中,**数组名**和**指针**在语法上有相似行为,但本质存在重要区别。以下是核心差异的详细分析: --- #### 1. **本质属性不同** - **数组名**:是**常量标识符**,代表一段连续内存空间的起始地址,不可修改。例如: ```cpp int arr[5] = {1,2,3,4,5}; arr = nullptr; // 编译错误:数组名不可重新赋值[^1] ``` - **指针**:是**变量**,存储某个内存地址,可以重新指向其他地址。例如: ```cpp int* p = arr; p = &arr[2]; // 合法操作 ``` --- #### 2. **`sizeof` 运算结果不同** - **数组名**:`sizeof(arr)` 返回**整个数组占用的字节数**。例如: ```cpp int arr[5]; cout << sizeof(arr); // 输出 5*sizeof(int),如20(int为4字节时) ``` - **指针**:`sizeof(p)` 返回**指针变量本身的字节数**(如32位系统为4字节,64位系统为8字节)。 --- #### 3. **取地址操作(`&`)的语义** - **数组名**:`&arr` 的类型是**数组指针**(如 `int(*)[5]`),指向整个数组的地址。例如: ```cpp int arr[5]; int (*p_to_array)[5] = &arr; // 数组指针类型[^3] ``` - **指针**:`&p` 返回指针变量自身的地址,类型为 `int**`(二级指针)。 --- #### 4. **类型信息保留** - **数组名**:包含**数组长度和元素类型**信息。例如: ```cpp void func(int arr[5]) { // 实际传递的是指针数组长度信息丢失[^1] } ``` - **指针**:仅存储地址,无法直接推导指向内存的完整类型和长度。 --- #### 5. **函数参数传递时的行为** - **数组名**:作为函数参数时,**退化为指向首元素的指针**。例如: ```cpp void Print(int *p) { /* 实际接收的是指针 */ } Print(arr); // 等价于 Print(&arr[0])[^5] ``` - **指针**:直接传递指针变量的值,行为一致。 --- #### 示例代码:数组名与指针的对比 ```cpp #include <iostream> using namespace std; int main() { int arr[5] = {1,2,3,4,5}; int* p = arr; cout << "sizeof(arr): " << sizeof(arr) << endl; // 输出20(假设int为4字节) cout << "sizeof(p): " << sizeof(p) << endl; // 输出8(64位系统) cout << "arr+1地址偏移: " << (void*)(arr+1) - (void*)arr << endl; // 4字节(int大小) cout << "&arr+1地址偏移: " << (void*)(&arr+1) - (void*)&arr << endl; // 20字节(整个数组大小) return 0; } ``` --- ### 注意事项 1. **禁止对数组名赋值**:`arr = new int[5];` 是非法操作。 2. **多维数组指针操作**:需使用数组指针(如 `int(*)[5]`)来正确访问元素。 3. **类型匹配**:数组指针与普通指针类型不兼容(如 `int(*)[5]` vs `int*`)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值