【C语言】指针的进阶

目录

前言:

1、字符指针

小练习:

2、指针数组

3、数组指针

3.1 数组指针定义

3.2 数组名与&数组名

 3.3 数组指针的使用

4. 数组参数、指针参数如何传参

4.1一维数组传参

4.2 二维数组传参

4.3 一级指针传参

4.4 二级指针传参

5. 函数指针

5.1 函数指针定义

小练习

6.  函数指针数组

7. 指向函数指针数组的指针

8. 回调函数

9.指针和数组的小练习1

总结:数组名的意义:1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。3. 除此之外所有的数组名都表示首元素的地址。

10. 指针小练习2


前言:

对于指针已知的知识点

1.指针是一种变量,即是用来存放一个最小内存单元(一个字节大小)的唯一地址,来标识这个存储空间,如一栋酒店里面每个房间的房间号。

2.指针的大小根据电脑的决定其大小,64位是8个字节,32位是4个字节。

3.指针的类型决定了

a.指针加减整数时的步长。如一个int* 类型的指针+1,就将在内存存储中移动四个字节;

b.指针在解引用操作时,其能访问内存的空间大小的权限。如一个char* 类型的指针解引用时只会访问一个字节的内存空间

4.指针的运算. 如指针加减整数;指针加减指针。

1、字符指针

char ch = 'a';
char* pa = &a;
*pa = 'b';

字符指针指向单个字符的创建、解引用的操作

const char* p = "woshixiaoba001";
*p = 'x' //error

字符指针指向一个常量字符串,

首先p存储的是字符串首字符的地址,而不是整个字符串的全部信息。因为常量字符串是常量不可以改变,所以对其指针解引用后想重新赋值是不行的。

小练习:

 因为str1 与str2是两个不同的字符数组(根据数组名,判断而不是数组中存放的内容),在创建数组时会各自在内存中开辟空间。因为数组名即首元素的地址,所以str1与str2不同。

因为“woshixiaoba001”是常量字符串,是单独存放在内存中的。将其首元素地址存入了两个不同名字的char*类型的指针,所以str3与str4两个指针中的地址都是字符串首元素地址,即字符‘w’的地址。因为是常量字符串,其内容是不能改变的,加上const增加鲁棒性。

2、指针数组

指针数组是数组,数组中元素的类型是指针。

int arr[8]; //整型数组
char* arr[10];//一级指针数组
double** arr[12];//二级指针数组

小应用1:通过字符指针存储一系列的字符串信息

小应用2:模拟创建二维数组

 在使用时可以写成二维数组的下标形式,也可以写成对指针解引用的形式。

3、数组指针

3.1 数组指针定义

数组指针是指针,是指向数组类型的指针。

char* pch //字符指针
int* pint //整型指针
float* pfloat //浮点型指针
int (*parr)[10] //数组指针
int *parr[10] //指针数组

如在创建数组指针int (*parr)[10] 时,必须要用()将解引用操作符*与指针变量名括在一起,表示这是一个指针变量,因为解引用操作符*与下标引用操作符[ ]相比前者优先级较低。然后[ ]表示这个指针是指向的是数组类型,数组中每个元素的类型为int.

3.2 数组名与&数组名

数组名一般默认为数组首元素的地址,如整型数组数组名对应的是整型指针变量,其类型是整型指针。若对其加减整数1,其偏移量在内存中是4个字节;对其解引用,则访问的是4个字节内存单元。

数组名只有两种情况表示整个数组

1、sizeof(单独存在数组名)-计算的是整个数组的大小,单位为字节。

2、&数组名-取出的是整个数组的地址。此时取出来的是一个数组指针变量,对应的类型是数组指针。若对其加减整数1,其偏移量是整个数组在内存中存储的字节大小;若对其解引用得到的是数组名,也就是首元素地址,类型又转换为数组元素对应的类型。

 

 3.3 数组指针的使用

//一维数组 数组形式传参;
void print1(int arr[10], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

//一维数组 指针形式传参(首元素地址,是指针类型跟元素的类型有关);
void print1(int *arr, int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", *(arr+i));
	}
	printf("\n");
}

//一维数组 指针形式传参(数组指针);
void print2(int(*p)[10], int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", (*p)[i]);//arr;
	}
	printf("\n");
}

 在一维数组中,数组指针传参使用较少,一般都以前两种形式居多。

//二维数组 数组形式传参
void print3(int arr[3][5], int r, int c)
{		 
	int i = 0;
	for (i = 0; i < r; i++)
	{
		int j = 0;
		for (j = 0; j < c; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}

//二维数组 数组指针形式传参
void print4(int (*p)[5], int r, int c)
{
	int i = 0;
	for (i = 0; i < r; i++)
	{
		int j = 0;
		for (j = 0; j < c; 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_arr1(arr, 3, 5);
    //数组名arr,表示首元素的地址
    //但是二维数组的首元素是二维数组的第一行
    //所以这里传递的arr,其实相当于第一行的地址,是一维数组的地址
    //可以数组指针来接收
    print_arr2(arr, 3, 5);
    return 0;
}

数组指针在二维数组传参时很好用!

小练习:

int arr[5];             这是整型数组;   
int *parr1[10];         这是整型指针数组;
int (*parr2)[10];       这是整型数组指针;
int (*parr3[10])[5];    这是整型数组指针数组

4. 数组参数、指针参数如何传参

4.1一维数组传参

#include <stdio.h>
void test(int arr[])// √    数组形式传参
{}
void test(int arr[10])// √    数组形式传参,下标引用为任何数都可以,不影响;
{}
void test(int *arr)// √    指针形式传参,传递首元素的地址
{}
void test2(int *arr2[20])// √    数组形式传参
{}
void test2(int **arr2)// √    指针形式传参,因为是整型指针数组,所以首元素地址是一个二级指针。
{}
int main()
{
 int arr[10] = {0};
 int *arr2[20] = {0};
 test(arr);
 test2(arr2);
}

4.2 二维数组传参

void test(int arr[3][5])// √
{}
void test(int arr[][])// ×
{}
void test(int arr[][5])// √
{}
//总结:二维数组数组形式传参,函数形参的设计只能省略第一个
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值