首页 > 其他分享 >指针(进阶)

指针(进阶)

时间:2024-10-27 10:47:52浏览次数:7  
标签:arr return 进阶 int void 数组 指针

1.字符指针

2. 数组指针

3.指针数组

4.数组传参和指针传参

5. 函数指针

6. 函数指针数组

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

8.相关的练习

指针的主题,我们在初级阶段的《指针》已经接触过了,我们知道了指针的概念:

1.指针就是个变量,用来存放地址,地址唯一标识一块内存空间。

2.指针的大小是固定的4/8个字节(32位平台/64位平台)。

3.指针是有类型,指针的类型决定了指针的+-整数的步长,指针解引用操作的时候的权限。

4.指针的运算。



int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 2,3,4,5,6 };
int arr3[] = { 3,4,5,6,7 };
int* parr[3] = { arr1, arr2, arr3 };
//0 1 2
int i = 0;
for (i = 0; i < 3; i++)
{
    int j = 0;
    for (j = 0; j < 5; j++)
    {
        printf("%d ",*(parr[i]+j));
    }
    printf("\n");
    }
return 0:
}

3.数组指针

3.1数组指针的定义

数组指针是指针?还是数组?

答案是:指针。

我们已经熟悉:

整形指针:int* pint;能够指向整形数据的指针。

浮点型指针:float*pf;能够指向浮点型数据的指针。

那数组指针应该是:能够指向数组的指针。

下面代码哪个是数组指针?

int *p1[10];

int (*p2)[10];

//p1,p2分别是什么?

p2的类型是数组指针 ->int (*)[10]

写成int* p=&arr会报警告,一个数组的地址不能用整型指针接收

int main()
{
	char* arr[5] = { 0 };
	char* (*pc)[5] = &arr;
	return 0;
}

pc是数组指针,数组类型是char*

二级指针是存放一级指针的地址

要写清楚有几个元素

指针数组常用用法

void print(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("%d",p[i][j]);
		}
		printf("\n");
	}
}

int main()
{
	int arr[3][5] = { 1,2,3,4,5,2,3,4,5,6,3,4,5,6,7 };
	print(arr, 3, 5);//二维数组的首元素地址是他的第一行的地址
	return 0;
}

*(p+i)相当于p[ i ]; 二维数组的数组名是它第一行的地址;所以arr相当于一个一维数组的地址

parr3存放的是类型为int (*)[ 5 ]的数组指针的数组,存放的数组指针指向的数组有5个int 类型的元素

parr3有10个数组指针的元素

4.数组参数,指针参数

4.1一维数组传参

#include <stdio.h>
void test(int arr[])
{}
void test(int arr[10])
{}
void test(int *arr)
{}
void test2(int *arr[20])
{}
void test2(int ** arr)
{}
int main()
{
int arr[10] = {0};
int *arr2[20] = {0};
test(arr);
test2(arr2);
}

arr2存放的是int* 的地址,可以用一个二级指针来接收

二维数组的数组名,表示首元素的地址,其实是第一行的地址

第一行是一个一维数组的!

5.函数指针

函数定义了就有地址

int add(int x, int y)
{
	return x + y;
}

int main()
{
	int arr[5] = { 0 };
	int(*p)[5] = &arr;
	int (*pc)(int, int) = &add;
	//int ret = (*pc)(2, 3);*可以省略不写,只是摆设
	int ret = pc(2, 3);
	int ret = add(2, 3);//pc存的是add的地址,两种写法是一样的
	printf("%d ", ret);

	return 0;
}

分析(*(void(*)())0)()是个什么鬼?(出自《C语言陷阱与缺陷》)

void (*)()是函数指针类型(我自己只能分析到这里,害~)

 void menu()
{
	printf("****1.jia    2.jian******\n");
	printf("****3.cheng  4.chu*******\n");
	printf("****0.exit        *******\n");
}

int jia(int x, int y)
{
	return x + y;
}

int jian(int x, int y)
{
	return x - y;
}

int cheng(int x, int y)
{
	return x * y;
}

int chu(int x, int y)
{
	return x / y;
}

void yiti(int (*pf)(int x, int y))
{
	int ret = 0;
	int x = 0;
	int y = 0;
	printf("请输入两个操作数:\n");
	scanf("%d %d", &x, &y);
ret=pf(x, y);
	printf("%d\n", ret);
}
//实现一个计算器,可以加减乘除
int main()
{

int input = 0;

	do
	{
		menu();
                printf("请选择:\n");
                scanf("%d", &input);
		switch (input)
		{
		case 1:
			yiti(jia);
			break;
		case 2:
			yiti(jian);
			break;
		case 3:
			yiti(cheng);
			break;
		case 4:
			yiti(chu);
			break;
		case 0:
			break;
		default:
			printf("选择错误\n");
		}
	} while (input);
	return 0;
}

这样就避免了很多冗余的代码

int (*arr[4])(int, int) = { jia,jian,cheng,chu };函数指针数组,用来存放函数指针

arr[4]数组的元素类型是int (*)(int,int)

函数指针数组的用法

int main()
{
	int x = 0;
	int y = 0;
	int ret = 0;
	int (*arr[5])(int, int) = { 0,jia,jian,cheng,chu };
	int input = 0;
	do
	{
		menu();
		scanf("%d", &input);
	if (input == 0)
	{
		printf("退出程序\n");
	}
	else if (input >= 1 && input <= 4)
	{
		printf("请输入两个操作数:\n");		
		scanf("%d %d", &x, &y);
		ret = arr[input](x, y);
		printf("%d", ret);
	}
	else
		printf("选择错误\n");
	} while (input);
	return 0;
}

这样更加简洁

还有指向函数指针数组的指针

int main()
{

	int (*parr[5])(int,int) = {0,jia,jian,cheng,chu};
	int (*(*pparr)[5])(int, int) = &parr;
	return 0;
}

qsort是标准库提供的排序函数

int cmp_int(void* e1, void* e2)//参数是指向两个整型的指针
{
	return *(int*)e1 > *(int*)e2;//先强制类型转换再解引用
}
int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, sizeof(arr[0]), cmp_int);
	for (int i = 0; i < sz; i++)
		printf("%d ", arr[i]);
	return 0;
}
struct stu
{
	int age;
	char name[20];
};

int cmp_name(const void* e1, const void* e2)
{
	return strcmp(((struct stu*)e1)->name, ((struct stu*)e2));
}

int cmp_age(const void* e1, const void* e2)
{
	return ((struct stu*)e1)->age - ((struct stu*)e2)->age;
}

int main()
{
	struct stu s[3] = { {17,"ti"},{11,"yiti"},{20,"huang"} };
	int sz = sizeof(s) / sizeof(s[0]);
	qsort(s, sz, sizeof(s[0]), cmp_age);
	return 0;
 }

可以对结构体的成员进行排序

模拟qsort

指针进阶练习

sizeof()括号内不是单独放数组名的话,都相当于首元素的地址

传给strlen的是一个指针

strlen要遇到0才停下来

sizeof计算的是数据和变量所占内存空间的大小

strlen求的是字符串长度

到这里就要理解为什么strlen(*arr)是会报错的,因为相当于传了一个数的地址给strlen

strlen(&p)是随机值,是从p的地址开始往下找,和字符串的内存空间是两回事,p只是存放字符串的首元素地址

也不确定是大端还是小端存储,所以是随机值

a[ 3 ]不是真的去访问二维数组的第四行,sizeof只要确定类型就可以计算字节大小

sizeof(int)是直接给类型,sizeof(a)函数会分析a的类型,其实是一样的

总结:

数组名的意义:

1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小

2.&数组名,这里的数组名表示整个数组,出的是整个数组的地址。

3. 除此之外所有的数组名都表示首元素的地址。

总结就是精华所在,万变不离其宗

标签:arr,return,进阶,int,void,数组,指针
From: https://blog.csdn.net/2402_83411382/article/details/143265488

相关文章

  • 面试 | 针对有经验的20个高频Python面试问题·进阶篇
    1.什么是字典和列表推导?Python推导式与装饰器一样,是语法糖结构,可帮助从给定的列表、字典或集合构建经过修改和过滤的列表、字典或集合。使用推导式可节省大量时间和代码,这些代码可能会更加冗长(包含更多代码行)。对整个列表执行数学运算my_list=[2,3,5,7,11]squared_......
  • 简单区分常量指针和指针常量的小技巧
    指针常量和常量指针介绍推荐一个文章,有介绍指针常量和常量指针,本文就不做另外的篇幅去介绍彻底理解——指针常量和常量指针、指向常量的常指针-CSDN博客区分的方法该方法简单好用,掌握了以后就再也不会分不清这两个东西了只要记住这句话:const默认是修饰它左边的符号的,如果左......
  • C语言——数组、指针、函数
    目录1、数组、指针、函数2、数组指针及指针数组2.1、数组指针2.2、指针数组2.3、区别3、指针函数与函数指针3.1、指针函数3.2、函数指针3.3、区别4、所有组合1、数组、指针、函数    在前面我们已经学习了数组、指针以及函数,看起来都没有难的地方,我自认......
  • 滑动窗口与双指针
    1.定长滑动窗口套路参考:灵神的总结入-更新-出:入:下标为i的元素进入窗口,更新相关统计量。如果i<k−1则重复第一步。更新:更新答案。一般是更新最大值/最小值。出:下标为i−k+1的元素离开窗口,更新相关统计量。for(inti=0;i<nums.size();++i){//1.进入......
  • Java面试真题之中级进阶(线程,进程,序列化,IO流,NIO)
    前言本来想着给自己放松一下,刷刷博客,慕然回首,线程、程序、进程?Java序列化?Java中IO流?JavaIO与NIO的区别(补充)?似乎有点模糊了,那就大概看一下Java基础面试题吧。好记性不如烂键盘***12万字的java面试题整理***简述线程、程序、进程的基本概念。以及他们之间关系是什......
  • 【Java知识】Java进阶-服务发现机制SPI
    文章目录SPI概述SPI工作原理ServiceLoader代码展示简化的`ServiceLoader`类关键点解释使用示例1.定义服务接口2.实现服务提供者3.配置文件4.加载服务提供者总结SPI使用场景1.数据库驱动2.日志框架3.图像处理4.加密算法5.插件系统6.缓存机制示例代码1.定......
  • 云服务器进阶-部署springboot项目
    一.通过finalshell登录自己的云服务器大家可以下载绑定资源中的finalshell,通过它来访问我们的服务器,二.访问宝塔面板接着我们输入bt进入上文中我们安装过的宝塔面板。输入14查看面板访问地址以及登陆的用户名密码,第一次登陆时会给我们生成一个默认密码,登录之后我们需要......
  • 【C语言】指针的运算
    目录1.指针加减整数2.指针减指针3.指针间的关系运算1.指针加减整数指针加减整数并不是简单的地址加减。在计算机内存中,每个变量都有一个唯一的存储位置,这个位置由其地址表示。当你对指针执行加法或减法操作,并传递一个整数值,实际上是改变了指针指向的位置,使其指向新......
  • 刷题总结——滑动窗口与双指针
    总结问题类型滑动窗口(同向双指针)定长不定长求最长/最大求最短/最小求子数组个数单序列双指针(同向/相向)同向:快排求partition的Lobos算法相向:三数之和(保证有序)注意去重双序列双指针双指针子序列判断多指针荷兰旗lowmidhigh00n初始化直到mid与high......
  • C语言指针练习
    题目如下:有1个班,3个学生,各学4门课,计算总平均分以及输出第n个学生的成绩示例代码如下:#include<stdio.h>intmain(){voidaverage(float*p,intn);voidsearch(float(*p)[4],intn);floatscore[3][4]={{65,67,70,60},{80,87,90,81},{90,99,100,98}};......