【C语言进阶】指针的进阶(1)

作者:@匿名者Unit
在这里插入图片描述

一.数组指针

1.定义

数组指针,顾名思义是指向数组的指针,那数组指针是如何定义的呢

int (*p)[10];
//解释:p先和*结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个
//指针,指向一个数组,叫数组指针。
//这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。

这就定义了一个指向大小为10的整形数组的指针。

2.使用

接下来我们看看数组指针的具体使用:

void print_arr2(int(*p)[5], int row, int col)
{
    
    
	int i = 0;
	for (i = 0; i < row; i++)
	{
    
    
		for (int j = 0; j < col; j++)
		{
    
    
			printf("%d ", (*(p+i))[j]);
		}
		printf("\n");
	}
}
int main()
{
    
    
	int arr[3][5] = {
    
     1,2,3,4,5,6,7,8,9,10 };
	print_arr2(arr, 3, 5);
	return 0;
}

如上的传参其实等同

int(*p)[5] = arr;

所以说arr就等同于p+0(*(p+i))[j] 等同于 p[i][j]

二.数组、指针传参

1.一维数组传参

void test(int arr[])//ok?
{
    
    }
void test(int arr[10])//ok?
{
    
    }
void test(int* arr)//ok?
{
    
    }
void test2(int* arr[20])//ok?
{
    
    }
void test2(int** arr)//ok?
{
    
    }

int main()
{
    
    
	int arr[10] = {
    
     0 };
	int* arr2[20] = {
    
     0 };
	test(arr);
	test2(arr2);
}

arr是一个一维数组通过test传递给函数时,形参可以直接用一维数组接受或者用指针接受,因为数组名代表着数组首元素,指针可以通过首元素地址找到数组所有元素。

2.二维数组传参

void test(int arr[3][5])//ok?
{
    
    }
void test(int arr[][])//ok?
{
    
    }
void test(int arr[][5])//ok?
{
    
    }
void test(int *arr)//ok?
{
    
    }
void test(int* arr[5])//ok?
{
    
    }
void test(int (*arr)[5])//ok?
{
    
    }
void test(int **arr)//ok?
{
    
    }
int main()
{
    
    
int arr[3][5] = {
    
    0};
test(arr);
}

二维数组数组名代表首元素地址,也就是第一行数组的地址,可以用二维数组直接作为形参接受,但是二维数组不可以省略列可以省略行。也可以使用数组指针 接受。

3.一级指针传参

当一个函数的参数部分为一级指针的时候,函数能接收什么参数?

  1. 变量的地址
  2. 一级指针
  3. 一维数组名

4.二级指针传参

当函数的参数为二级指针的时候,可以接收什么参数?

  1. 二级指针
  2. 一级指针的地址
  3. 指针数组名

三.函数指针

函数也有地址,可以对函数进行取地址操作。
在这里插入图片描述

函数指针就是存放函数地址的一种指针。

接下来我们看两段代码 来理解函数指针:

//代码1
(*(void (*)())0)();
//代码2
void (*signal(int , void(*)(int)))(int);

代码1其实是一次函数调用(函数名参数
将0作为一个地址,强制转换为void(*)()的函数指针,再调用。


代码2则更好理解,signal函数有两个参数:int和void(*)(int)的函数指针类型
signal函数返回的是一个函数指针,此函数指针参数为int,返回类型为void
为了便于我们理解,可以写成这样

void (*)(int)   signal(int, void(*)(int));

但是这样书写是错误的,当函数返回类型为函数指针的时候不能像普通函数一样,将返回类型写在函数名字前面,而是要将函数体当做函数指针的名字编写


还有当使用typedef重命名函数指针时,也不能 想普通变量一样将新名字写在类型后面如:

typedef long double lble;
typedef void(*)(int)  pfun_t;//错误的

而是要将新名字写在函数指针的名字的位置:

typedef void(*pfun_t)(int);//正确的

猜你喜欢

转载自blog.csdn.net/qq_43289447/article/details/128554674