C语言——深入理解指针(3)

这篇具有很好参考价值的文章主要介绍了C语言——深入理解指针(3)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1. 字符指针

2. 数组指针

2.1 数组指针变量

2.2 数组指针变量的初始化

3.二维数组传参(本质)

4. 函数指针

4.1 函数指针变量的创建

4.2 函数指针的使用

4.3 typedef 

5. 函数指针数组

6. 转移表(函数指针数组的使用)


C语言——深入理解指针(3),C语言,c语言,开发语言

1. 字符指针

在指针的类型中有一种指针类型为字符指针 char*

#include<stdio.h>
int main()
{
	char ch = 'h';
	char* pc = &ch;//pc就是字符指针
	const char* pstr = "hello";//常量字符串
    //这里不是把字符串存在p中,而是把第一个字符的地址存放在p中
	//1,你可以把字符串相信成一个字符数组
	//2.当常量字符串出现在表达式中的时候,他点值是第一个字符的地址
	printf("%c\n", "hello"[3]);
	printf("%s\n", pstr);
}

 C语言——深入理解指针(3),C语言,c语言,开发语言

 举例:

#include <stdio.h>
int main()
{
	char str1[] = "hello bit.";
	char str2[] = "hello bit.";
	const char* str3 = "hello bit.";
	const char* str4 = "hello bit.";
	if (str1 == str2)//str1和str2是两个不同地址的字符数组。
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");

	if (str3 == str4)//str3和str4指向的是同一个常量字符串。
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");

	return 0;
}

 注意:内容相同的常量字符串只会保存一份。

2. 数组指针

2.1 数组指针变量

在前面的文章中,我们学了指针数组,它是一种数组,里面存的是地址(指针)。

数组指针其实跟指针数组不同,数组指针是:指针变量。

我们回忆一下指针之前的一些指针变量:

整形指针变量: int * p1; 存放的是整形变量的地址,能够指向整形数据的指针。

浮点型指针变量: float * p2; 存放浮点型变量的地址,能够指向浮点型数据的指针。

那么数组指针变量就应该是:存放的是数组的地址,能够指向数组的指针变量。

数组指针变量
int (*p)[10];
p先和*结合,说明p是⼀个指针变量变量,然后指着指向的是⼀个⼤⼩为10个整型的数组。

注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合

2.2 数组指针变量的初始化

int arr[10] = {0};
&arr;//得到的就是数组的地址
int(*p)[10] = &arr;//p数组指针指向arr数组的指针
&arr表示整个数组的地址

 数组指针类型:

int (*p) [10] = &arr;
 | | |
 | | |
 | | p指向数组的元素个数
 | p是数组指针变量名
 p指向的数组的元素类型

3.二维数组传参(本质)

之前我们需要把一个二维数组传参给一个函数的时候,我们是这么写的

#include <stdio.h>
void test(int a[3][5], int r, int c)//这里的形参是二维数组
{
	int i = 0;
	int j = 0;
	for (i = 0; i < r; i++)
	{
		for (j = 0; j < c; j++)
		{
			printf("%d ", a[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} };
	test(arr, 3, 5);
	return 0;
}

 那还有什么其他的写法吗?

C语言——深入理解指针(3),C语言,c语言,开发语言

 我们可以看到二维数组可以被分为多个一维数组,可以把每个一维数组看成一个元素,那么二维数组的首元素就是第一个一维数组。根据数组名是数组⾸元素的地址这个规则,⼆维数组的数组名表示的就是第⼀⾏的地址,是⼀维数组的地址。既然是数组地址我们就要用数组指针 int (*p)来存,但是一维数组里面还有很多数,这时我们就要在数组指针后面加个数组 int(*p)[] ,来把这些数存下来。

⼆维数组传参本质上也是传递了地址,传递的是第⼀行这个⼀维数组的地址。

int main()
{
	int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6},{3,4,5,6,7} };
	test(arr, 3, 5);
	return 0;
}
#include <stdio.h>
void test(int (*p)[5], int r, int c)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < r; i++)
	{
		for (j = 0; j < c; j++)
		{
			printf("%d ", a[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} };
	test(arr, 3, 5);
	return 0;
}

总结:⼆维数组传参,形参的部分可以写成数组,也可以写成指针形式。

4. 函数指针

4.1 函数指针变量的创建

根据我们前面学的指针变量,我们大概可以推出,函数指针变量就是用来存放函数地址的,后面可以通过地址来调用函数。

C语言——深入理解指针(3),C语言,c语言,开发语言

函数是有地址的,且函数名就是函数的地址,我们可以通过&函数来获得函数的地址。要存地址,那就要用到指针,存函数的地址,就要用函数指针。函数指针的创建跟数组指针差不多。

int (*p) (int x, int y)
 |     | ------------ 
 |     |     |
 |     | p指向函数的参数类型和个数的交代
 |     |
 |     函数指针变量名
 |
 p指向函数的返回类型

举例:

#include <stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	//int(*pf3)(int, int) = Add;
	int(*pf3)(int x, int y) = &Add;//x和y写上或者省略都是可以的
	printf("%p\n", pf3);
	return 0;
}

4.2 函数指针的使用

#include <stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	//int(*pf3)(int, int) = Add;
	int(*pf3)(int x, int y) = &Add;
	printf("%d\n", pf3(1, 2));//pf3(1, 2)==Add(1,2)
	printf("%d\n", (*pf3)(1, 2));
	return 0;
}

 我们根据之前学的来看两个代码

(*(void (*)())0)();

C语言——深入理解指针(3),C语言,c语言,开发语言

void (*signal(int , void(*)(int)))(int);
//1.signal是一个函数声明
//2.signal函数的第一个参数的类型是int
// signal函数的第二个参数的类型是函数指针:void(*)(int)
//这个函数指针指向的函数参数是int类型,返回类型是void
//3. signal函数的返回类型也是一个函数指针:void(*)(int)
//这个函数指针指向的函数参数是int类型,返回类型是void

4.3 typedef 

typedef 是用来给类型重名的,可以将复杂的类型,简单化。

typedef unsigned int uint;
//将unsigned int 重命名为uint

指针类型一样可以重命名。

typedef int* ptr_t;
//将 int* 重命名为 ptr_t

注意:数组指针和函数指针的类型重名有点不同

数组指针:

typedef int(*parr_t)[5]; //新的类型名必须在*的右边
//将指针类型 int(*)[5] ,重命名为 parr_t

函数指针:

typedef void(*pfun_t)(int);//新的类型名必须在*的右边
//将 void(*)(int) 类型重命名为 pf_t

5. 函数指针数组

数组是一个存放相同类型数组空间。那把函数的地址存到⼀个数组中,那这个数组就叫函数指针数组。

int (*parr1[3])();
int (*)() 类型的函数指针。

6. 转移表(函数指针数组的使用)

计算机的实现:文章来源地址https://www.toymoban.com/news/detail-755173.html

#include <stdio.h>
int add(int a, int b)
{
	return a + b;
}
int sub(int a, int b)
{
	return a - b;
}
int mul(int a, int b)
{
	return a * b;
}
int div(int a, int b)
{
	return a / b;
}
int main()
{
	int x, y;
	int input = 1;
	int ret = 0;
	int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表--函数指针数组的存入
	do
	{
		printf("*************************\n");
		printf(" 1:add 2:sub \n");
		printf(" 3:mul 4:div \n");
		printf(" 0:exit \n");
		printf("*************************\n");
		printf("请选择:");
		scanf("%d", &input);
		if ((input <= 4 && input >= 1))
		{
			printf("输入要求的数:");
			scanf("%d %d", &x, &y);
			ret = (*p[input])(x, y);//函数指针数组的元素使用
			printf("ret = %d\n", ret);
		}
		else if (input == 0)
		{
			printf("退出计算器\n");
		}
		else
		{
			printf("输入错误,请重新输入\n");
		}
	} while (input);
	return 0;
}

到了这里,关于C语言——深入理解指针(3)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言深入理解指针(非常详细)(四)

    字符指针在之前我们有提到过,(字符)(指针)前面的字符代表着存储的元素为字符类型,而指针则是表示这存储的方式。 写法为char * 一般使用的方式如下: 还有一种使用方式如下: 值得注意的是: 代码 const char pstr = “hello jack.”; 特别容易以为是把字符串 hello jack 放到

    2024年02月09日
    浏览(61)
  • 【C语言基础】:深入理解指针(三)

    指针系列回顾 : 【C语言基础】:深入理解指针(一) 【C语言基础】:深入理解指针(二) 一、冒泡排序 冒泡排序的核心思想就是:两两相邻的元素进行比较。 可以看到,这段代码对arr数组进行了排序,但这个代码还有一些缺陷,那就是无论数组内部的元素是否有序,他都会循

    2024年03月10日
    浏览(41)
  • C语言深入理解指针(非常详细)(一)

    在将内存和地址时我们先举一个生活中的例子: 假设有⼀栋宿舍楼,把你放在楼里,楼上有100个房间,但是房间没有编号,你的⼀个朋友来找你玩, 如果想找到你,就得挨个房子去找,这样效率很低,但是我们如果根据楼层和楼层的房间的情况,给每个房间编上号,如: 有

    2024年02月10日
    浏览(38)
  • C语言深入理解指针(非常详细)(二)

    指针的基本运算有三种,分别是: • 指针±整数 • 指针-指针 • 指针的关系运算 因为数组在内存中是连续存放的,比如int类型的数组,每个元素相差4个字节,因此我们只需要知道首元素的地址就可以通过加减的方式找到后面元素的地址 。 概念:野指针就是指针指向的位置

    2024年02月10日
    浏览(42)
  • C语言——从头开始——深入理解指针(1)

     一.内存和地址 我们知道计算上CPU(中央处理器)在处理数据的时候,是通过地址总线把需要的数据从内存中读取的,后通过数据总线把处理后的数据放回内存中。如下图所示: 计算机把内存划分为⼀个个的 内存单元 ,每个内存单元的大小取1个字节( 1个字节(Byte)=8个比特

    2024年02月21日
    浏览(46)
  • 【C语言】指针的入门篇2,深入理解指针和数组的关系

    欢迎来CILMY23的博客喔,本期系列为【C语言】指针的入门篇2,深入理解指针和数组的关系,图文讲解指针和数组关系的知识,带大家理解指针和数组的关系,以及指针+数组的用法,感谢观看,支持的可以给个赞哇。 前言 在上一篇博客中,我们了解了指针就是地址,并且把地

    2024年02月20日
    浏览(49)
  • C语言之指针篇【超详细讲解,带你层层深入理解指针】

    目录 一、关于指针 二、指针类型 1、整型指针的访问权限说明: 2、字符指针的访问权限说明: 3、指针的类型决定向前或向后一步走了多大距离 三、野指针相关知识 1、野指针的成因 ①指针未初始化 ②指针的越界访问 ③指针所指向的空间释放了 2、如何规避野指针 ①指针

    2024年02月02日
    浏览(38)
  • C语言指针(适合C语言进阶者):一道题带你深入理解数组与指针的关系

    🎈个人主页:JAMES别扣了 💕在校大学生一枚。对IT有着极其浓厚的兴趣 ✨系列专栏目前为C语言初阶、后续会更新c语言的学习方法以及c题目分享. 😍希望我的文章对大家有着不一样的帮助,欢迎大家关注我,我也会回关,大家一起交流一起互动,感谢大家的多多支持哈! 🎉

    2024年04月16日
    浏览(54)
  • 对指针的深入理解

    在讲解本次内容前,先来看个小栗子: 我们在代码中定义了一个更安全的 free 函数 safe_free ,在该函数中我们事先对指针 ptr 进行了参数校验,并在 free 后及时将其置 NULL,目的是为了防止野指针的出现。 下面让我们来运行一下: 那么疑问来了:在调用 safe_free(p) 时,我明明

    2024年02月05日
    浏览(41)
  • 深入理解ArkTS:Harmony OS 应用开发语言 TypeScript 的基础语法和关键特性

    Harmony OS应用开发的主力语言ArkTS的前身TS语言的基本语法。通过学习变量的声明和数据类型、条件控制、函数声明、循环迭代等基本知识,并了解内核接口的声明和使用。同时还介绍了模块化开发的概念,提高代码的复用性和开发效率。该对话还涉及了if else和switch条件控制语

    2024年02月04日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包