知识点9:一些指针类型

指针类型

指针类型和指针所指向的类型是两个概念。
从语法角度来看:对于指针声明语句,去掉其中的指针名,剩下的便是该指针类型;去掉指针名和前面的*号,剩下的便是指针所指向的类型。

指针声明语句 指针类型 指针所指向的类型
int *p; int* int
int **p; int** int*
int (*p)[ 5 ]; int ( * )[ 5 ] int ()[ 5 ]
int *(*p)[ 5 ]; int *( * )[ 5 ] int *()[ 5 ]

只要有一段内存, 并且这段内存存储的内容具有固定的类型,就可以定义一个指向它的指针。
指针所指向的类型可通过测量*p所占空间sizeof(*p)来验证。

1, 指向一维数组的指针: int (*p)[10]

该声明表明p是一个指向“长度”为10的整型数组的指针。也就是说加减运算单元为一整个数组。
对于二维数组:
二维数组的操作单元就是一个一维数组。因此在对指向一维数组的指针赋值时,直接赋给数组名即可:int (*p)[10] = array;(&和*互为逆运算,因此也可写作:int (*p)[3] = &a[0];
赋值之后p可视作一个二维数组,可以进行p[0][0]这样的运算,但要注意p指针所指向的位置(p所指向的位置会作为原点)。作为二维数组,进行p++运算时的单位元为一维数组,因此进行p++操作,便可切换到下一个一维数组;(*p)便可视作是一个一维数组。

	int a[3][3] = {
    
    1, 2, 3, 4, 5, 6, 7, 8, 9};
	int (*p)[3] = a;
	printf("%d\n", p[0][0]);//输出1
	printf("%d\n", (*p)[1]);//输出2   (*p)[1]相当于a[0][1]
	p ++;
	printf("%d\n", (*p)[1]);//输出5   此处(*p)[1]相当于a[1][1]
	printf("%d\n", (*(p+1))[1]);//输出8	
	printf("%d\n", *(*p+1));//输出5           *p可视作一维数组
	printf("%d\n", p[0][0]);//输出4   p所指的位置不再是a[0][0]而是a[1][0],因此导致p[0][0]的值与a[0][0]不同

对于一维数组:
赋值时若直接赋数组名,数组名实则只是首元素的地址,那么指针只指向单个数组元素。为指向整个数组,在赋值时应该将一维数组“放大”:int (*pt)[10] = &array;(用上了&运算符)(*运算符使更细化,&运算符则相反)
赋值之后,p可视作一个第一维为0的“二维数组”,可进行p[0][1]这样的运算;(*p)便可视作一维数组。因为p已经指向了整个一维数组,因此p++运算已没有意义。

	int a[9] = {
    
    1, 2, 3, 4, 5, 6, 7, 8, 9};
	int (*p)[9] = &a;
	printf("%d\n", p[0][1]);//输出2
	printf("%d\n", (*p)[1]);//输出2        (*p)[1]相当于a[1]

2,指向函数的指针

函数具有可赋值给指针的物理内存地址,一个函数的函数名就是一个指针,是该函数的入口。函数的调用可以通过函数名,也可以通过指向函数的指针来调用。
定义形式例如int (*p)(int i, int j);也可简化为int (*p)(int, int);表明p指向的是一个返回值为整型且需要两个整型参数的函数。定义之后,再将函数名赋给指针,便可将(*p)视作函数名,进行使用。

#include<stdio.h>
int max(int x, int y)
{
    
    
	return(x > y ? x : y);
}
int main()
{
    
    
	int (*p)(int, int);//定义一个指向函数的指针变量 
	int a, b, c;
	p = max;//将函数的入口地址赋给p,此时p和max都指向函数的开头 
	scanf("%d%d", &a, &b);
	c = (*p)(a, b);//调用*p就是调用max函数 
	printf("%d", c);
	return 0;
} 

运用指向函数的指针可以实现视不同情况调用不同函数,十分方便。

#include <stdio.h>
int max(int x, int y)
{
    
    
	return(x > y ? x : y);
}
int min(int x, int y)
{
    
    
	return(x < y ? x : y);
}

int main() 
{
    
    
	int (*p)(int, int);//定义一个指向函数的指针变量,它可以指向 函数类型为int,且有两个int型参数 的函数 
	int a, b, c, n;
	scanf("%d%d%d", &a, &b, &n);
	//函数名代表函数的入口地址(起始地址、指针) 
	if (n == 1) p = max;//将函数的指针赋给指针变量,只需给出函数名即可 
	if (n == 0) p = min;//根据输入的n的值来判断调用哪个函数
	c = (*p)(a, b);//(*p)即p所指向的函数名。     表达式唯一(方便!) 
	printf("%d", c);
	return 0;
}

注意区分int *函数名(参数列表)int (*p)(参数列表)前者定义的是返回指针的函数,后者定义的是指向函数的指针。

3,指向结构体的指针

定义时令指针的类型为所创的结构体类型即可,定义之后(*p)相当于所设的结构体变量。

	struct Student
	{
    
    
		long num;
		char name[20];
	}s[3] = {
    
    {
    
    10101, "Tom"}, {
    
    10102, "Jack"}, {
    
    10103, "Join"}};
	struct Student *p;
	for (p = s; p < s + 3; p ++)//将结构体数组的地址赋给指针变量 
	{
    
    
		printf("%ld\t%s\n", (*p).num, (*p).name);//(*p)表示p指向的结构体变量,(*p).num表示p所指向的结构体变量中的成员num 
		printf("%ld\t%s\n", p->num, p->name);//更加形象化地表示"指向",两种表示的效果相同
	}

猜你喜欢

转载自blog.csdn.net/Shao_yihao/article/details/113253609