C语言–指针详解(下)–字符指针、数组指针、指针数组、函数指针、函数指针数组(转移表)

C语言–指针详解(下)–字符指针、数组指针、指针数组、函数指针、函数指针数组(转移表)

  • 1. 字符指针
  • 2. 数组指针
  • 3. 指针数组
  • 4. 函数指针
  • 5. 函数指针数组(转移表)
  • 6. 总结

1. 字符指针

在C语言中有一种指针类型为字符指针 char*,常用其来表示字符,使用如下:

#include <stdio.h>
int main()
{
	char ch = 'w';
 	char *pc = &ch;
 	*pc = 'w';
 	return 0;
}

除了上述用法之外,还可以有以下的用法:

int main()
{
 const char* pstr = "hello word";
 printf("%s\n", pstr);
 return 0;
 }

在上面的代码中,字符 ” hello word “是常量字符串,将”hello word”放入 pstr 指针的实质是将第一个字符 “ h ” 的地址传递给了 pstr ,通过首字符 ” h ” 就可以访问整个字符串。

注意:常量字符串传递给不同的字符指针变量的时候,传过去的地址是相同的,因为常量字符串是存放在静态区的,它的地址是唯一的。

如下面这道例题:

#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");
 else

 printf("str1 and str2 are not same\n");
 
 if(str3 ==str4)
 printf("str3 and str4 are same\n");
 else

 printf("str3 and str4 are not same\n");
 
 return 0;
}

结果如下:

2. 数组指针

数组指针其本质是指针,数组是用来修饰指针的,表明这个指针是用来存放数组的,即其存放的数据类型是数组。

那如何表示呢?

首先,是一个指针,那么一定有 *arr
其次数据类型是数组(以10个整形类型为例),则一定有int [ 10 ]
合起来便是 int (*arr)[ 10 ],即 arr 是⼀个指针,指向⼀个数组,叫数组指针。
因为 [] 与arr结合的优先级要优先于 * ,因而要加括号;否则就变为了指针数组(详细见下指针数组)

数组指针类型解析:

int (*p) [10] = &arr;
 |    |   |
 |    |   |
 |    |   p指向数组的元素个数
 |    p是数组指针变量名
 p指向的数组的元素类型

数组指针变量是⽤来存放数组地址的,那怎么获得数组的地址呢?就是我们之前学习的 &数组名

	int a[10] = {0};
	&a;//得到的就是数组的地址 

如果要存放个数组的地址,就得存放在数组指针变量中,如下:

int(*arr)[10] = &a;

使用如下:

//以打印第一个数据为例
printf("%d", *(arr+0));
//等价于:printf("%d", a[0]);

在此处便可以很好看出数组名其实就是数组的首地址,有以下等价式:

*(p + i) = p[i] = arr[i] =*(arr + i) = i[arr]

详情见**“数组名的理解”**:C语言–指针详解(中)–指针的基本使用、指针在数组中的应用

3. 指针数组

指针数组其本质是数组,指针是用来修饰数组的,表明这个数组是用来存放指针的,即其存放的数据类型是指针。

那如何表示呢?(与上述数组指针对比)

首先,是一个数组(以10个整形类型为例),那么一定有 arr[10]
其次数据类型是指针,则一定有int *
合起来便是 int * arr[ 10 ],即 arr 是⼀个数组,指向一个由指针组成的数组,叫指针数组。
因为 [] 与arr结合的优先级要优先于 * ,因而不用加括号。

指针数组类型解析:

int*  p [10] = &arr;
 |    |   |
 |    |   |
 |    |   p指向数组的元素个数
 |    p是指针数组变量名
 p指向的数组的元素类型
char p1 = 'a';
char p2 = 'b';
char p3 = 'c';
char p4 = 'd';
int* arr[10] ={ &p1, &p2, &p3, &p4 };

指针数组一般用于存放多个指针类型的数据,且一般不单独使用,主要用于组成转移表,详细见下转移表。

4. 函数指针

函数指针变量是⽤来存放函数地址的,通过地址就能够调⽤函数。

其基本形式为:int (*arr) (int,int)

函数指针类型解析:

int (*pf3) (int x, int y)
 |     |    ------------ 
 |     |        |
 |     |        pf3指向函数的参数类型和个数的交代
 |    函数指针变量名
 pf3指向函数的返回类型
 
 int (*) (int x, int y) //pf3函数指针变量的类型 

有以下三种形式:

void test()
{
 printf("hehe\n");
}
void (*pf1)() = &test;
void (*pf2)()= test;//函数名在本质上也是地址,&函数名==函数名
int Add(int x, int y)
{
 return x+y;
}

int(*pf3)(int, int) = Add;

int(*pf3)(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;
}

输出结果:

5
8

5. 函数指针数组(转移表)

把函数的地址存到⼀个数组中,那这个数组就叫函数指针数组。

基本形式:int (*parr1[3])();

parr1 先和 [ ] 结合,说明parr1是数组,数据类型是 int ( * )( ) 类型的函数指针

函数指针数组的⽤途:转移表

举例:计算器的⼀般实现:

#include <stdio.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;
	 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);
		 switch (input)
		 {
			 case 1:
				 printf("输⼊操作数:");
				 scanf("%d %d", &x, &y);
				 ret = add(x, y);
				 printf("ret = %d\n", ret);
				 break;
			 case 2:
				 printf("输⼊操作数:");
				 scanf("%d %d", &x, &y);
				 ret = sub(x, y);
				 printf("ret = %d\n", ret);
				 break;
			 case 3:
				 printf("输⼊操作数:");
				 scanf("%d %d", &x, &y);
				 ret = mul(x, y);
				 printf("ret = %d\n", ret);
				 break;
			 case 4:
				 printf("输⼊操作数:");
				 scanf("%d %d", &x, &y);
				 ret = div(x, y);
				 printf("ret = %d\n", ret);
				 break;
			 case 0:
				 printf("退出程序\n");
				 break;
				 default:
				 printf("选择错误\n");
				 break;
		 }
	 } while (input);
	 return 0;
 }

使⽤函数指针数组的实现:

#include <stdio.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;
	 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;
}

6. 总结

字符指针、数组指针、指针数组、函数指针、函数指针数组涵盖了在指针学习中有关指针的绝大多数的情况,熟练掌握它们,将对学习指针有巨大的帮助。同时,指针部分是C语言学习中重要的部分之一,熟练掌握指针对于C语言学习来说很重要。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2023年12月27日
下一篇 2023年12月27日

相关推荐