C语言指针--第二篇

100 阅读4分钟

目录

1.函数指针
1.1如何定义一个函数指针
1.2如何使用函数指针
2.指针数组
3.指针函数
4.多级指针
4.1认识二级指针和多级指针
4.2 二级指针的用法
4.3二级指针不能简单粗暴指向二维数组
5.总结

1.函数指针

1.1如何定义一个函数指针

如果程序中定义了一个函数,在编译时,编译系统为函数代码分配一段储存空间,这段储存空间的初始地址(又称入口地址),称为这个函数的指针。

函数名==地址!!(就像数组中,数组名==地址)

Int (*p)(int); 从P处开始,先与指针结合,说明P是一个指针,然后与( )结合,说明指针指向的是一个函数,然后再与( )里的int结合,说明函数有一个int型的参数,再与最外层的int结合,说明函数的返回类型是整型,所以P是一个指向有一个整型参数且返回类型为整型的函数的指针。

1.2如何使用函数指针

void printWelcom()
{
  puts("程序启动,欢迎使用!\n");
}
int inCData(int data)
{
  return ++data;
}
int main()
{ 
  void (*p)();//定义了一个函数指针变量
  int(*p2)();
  
  p = printWelcom;//指向函数
  p2=inCData;

  (*p)();//调用
  printf("p2测试:%d\n",(*p2)(10));
  return 0;
}

巧妙理解:以普通指针做对比

int a;//声明一个变量
int \*pa;//声明一个指针变量
pa=&a;

printWelcom( );  //声明一个函数
void (\*p)( );  //声明一个函数指针
p=printWelcom; //函数名==地址!!

2.指针数组

前文提到的数组指针 int (*p)[4] 是指向数组的指针,这个指针是含有4个元素的一维数组。
而指针数组是一个数组,其元素均为指针类型, 换句话说,指针数组中的每一个元素都存放一个地址

定义为: int *p[4]

int main()
{
  int a = 10;
  int b = 20;
  int c = 30;
  int d = 40;
  int* p[4] = { &a,&b,&c,&d };
  for (int i = 0;i < 4;i++)
  {
	  printf("%d ", *p[i]);
  }
  return 0;
}

3.指针函数

一个函数可以返回一个整形值,字符值,实型值,也可以返回指针型的数据,即地址。概念与前文类似,只是返回的值是指针类型而已。

例如“int *a(int x, int y);”, a是函数名,调用他以后能得到一个 int*型(指向整形数据)的指针,即整形数据的地址。 x和y是函数a的形式参数。

问题:有a个学生,每个学生有b门课程的成绩。要求在用户输入学生序号以后,能输出该学生的全部乘机。用指针函数实现。
int* getPosPerson(int pos, int(*pstu)[4])//指针函数,返回指针的函数
{
	int* p;
	p = (int*)(pstu + pos);//偏移
	return p;
}

int main()
{
	int scores[3][4] = {
		{55,66,77,88},
		{66,55,99,100},
		{11,22,33,59},
	};
	int* ppos;
	int pos;
	printf("请输入你需要看的学生号数:0,1,2\n");
	scanf("%d", &pos);

	ppos = getPosPerson(pos, scores);
	for (int i = 0;i < 4;i++) {
		printf("%d ", *ppos++);
	}
	return 0;
}

4.多级指针

4.1认识二级指针和多级指针

写法**p

int main()
{
    int data = 100;
	int *p = &data;
	printf("data的地址是:%p\n",&data);
	printf("p保存data的地址:%p,内容是%d\n",p,*p);
	/*可以用一级指针变量存放指针变量的地址,但是使用有缺陷,无法获得最终地址内容
	printf("p的地址是:%p\n",&p);
	int *pp = &p;
	printf("pp保存p的地址:%p\n",pp);
	printf("*pp是%p\n",*pp);*/
	
	int **p2;//二级指针
	p2 = &p;
	printf("p2保存p的地址:%p\n",p2);
	printf("*p2是%p\n",*p2);
	printf("**p2来访问data:%d\n",**p2);
	
	int ***p3;//三级指针
	p3 = &p2;
	printf("p3保存p2的地址:%p\n",p3);
	printf("*p3是%p2\n",*p3);
	printf("***p3来访问data:%d\n",***p3);
	return 0;
}

4.2 二级指针的用法

void getPosPerson(int pos, int(*pstu)[4], int **ppos)//指针函数,返回指针的函数
{
	*ppos = (int*)(pstu + pos);//偏移
}

int main()
{
	int scores[3][4] = {
		{55,66,77,88},
		{66,55,99,100},
		{11,22,33,59},
	};
	int* ppos;
	int pos;
	printf("请输入你需要看的学生号数:0,1,2\n");
	scanf("%d", &pos);

	getPosPerson(pos, scores,&ppos);
	for (int i = 0;i < 4;i++) {
		printf("%d ", *ppos++);
	}
	return 0;
}

4.3二级指针不能简单粗暴指向二维数组

int main()
{
	int scores[3][4]={
		{55,66,77,88},
		{66,55,99,100},
		{11,22,33,59},
	};//int (*p)[4];
	int (*p2)[4] = scores;
	
	int **p; 
	p = scores;  //会出问题!
	printf("scores:%p\n",scores);
	printf("p=%p\n",p);
	printf("*p=%p\n",*p);//*p是一个野指针,不是我们认为的会编程列地址
	printf("*score=%p\n",*scores);//*p是一个野指针,不是我们认为的会编程列地址
	
	**p = 100;
	printf("done\n");
	
	int **p3 = &p2;//能用
	**p3 = 100;//能改的动,但是一般不这么进行
	printf("%d\n",scores[0][0]);
	return 0;
}

5.总结

C语言指针 两篇主要讲了:①指针是什么 ②为什么用指针 ③指针与数组的关系 ④数组指针 ⑤函数指针 ⑥指针数组 ⑦指针函数 ⑧二级指针

面试题会出现:

image.png