IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 详细讲解C语言15(C语言系列) -> 正文阅读

[C++知识库]详细讲解C语言15(C语言系列)

目录

前言:

初阶指针的概念回顾:

字符指针:

指针数组:

数组指针:?

数组指针的定义:

&数组名vs数组名:

数组指针应该怎么用??

一维数组:?

二维数组:?

数组参数、指针参数:

一维数组传参:

?二维数组传参:

一级指针传参:?

二级指针传参:?

函数指针:?

函数指针数组:

指向函数指针数组的指针:

回调函数:

结束语:


前言:

之前我和大家分享过初识指针的一些知识,如果没有看过的小伙伴请点击这里去康康吧(http://t.csdn.cn/kGepB),那接下来我会继续深入指针与大家继续分享指针相关的一些知识,大家快来一起学习吧!

初阶指针的概念回顾:

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

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

3.指针是有类型的,指针的类型决定了指针的+ -?整数的步长,以及指针解引用时的权限大小。

4.指针的运算。

字符指针:

(char*):存放字符的指针。

代码展示:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	char ch = 'W';
	char* pc = &ch;//pc为字符指针
	char* ps = "abcdef";//ps为常量字符串指针
	//*ps = 'w';
	printf("%c\n", *ps);
	return 0;
}


代码运行结果:

修改值的时候常量字符串是不能被修改的。?

如下所示:?

下面我们来看一下以下这个代码:
代码展示:

#define _CRT_SECURE_NO_WARNINGS 1
#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)
	{
		printf("str1 and str2 are same\n");
	}
	else
	{
		printf("str1 and str2 are not same\n");
	}
	if (str3 == str4)
	{
		printf("str3 and str4 are same\n");
	}
	else
	{
		printf("str3 and str4 are not same\n");
	}
	return 0;
}

代码运行结果:

解析:

两个字符串用等号(==)来比较的时候比较的是两个字符串的首地址,要比较字符串内容的时候则要采用strcmp来进行比较。

指针数组:

指针数组是一个存放指针的数组。

int*?arr[10]整形指针的数组
char* arr2[10]一级字符指针的数组
char** arr3[4]二级指针数组的数据

代码展示:

#define _CRT_SECURE_NO_WARNINGS 1
//指针数组---存放指针的数组
#include<stdio.h>
int main()
{
	char* arr[5] = { "abcdef","zhangsan","wnagwu","lisi","ruhua" };//存放的是数组的首地址
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%s ", arr[i]);
		printf("\n");
	}
	return 0;
}


代码运行截图:

解析:
?

?

练习:用一维数组模仿实现一个二维数组。

代码展示:
?

#define _CRT_SECURE_NO_WARNINGS 1
//用一维数组模仿实现一个二维数组
#include<stdio.h>
int main()
{
	int arr1[5] = { 1,2,3,4,5 };
	int arr2[5] = { 2,3,4,5,6 };
	int arr3[5] = { 3,4,5,6,7 };
	int* arr[] = { arr1,arr2,arr3 };
	int i = 0;
	int j = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

代码运行结果:

解析:

数组指针:?

数组指针的定义:

数组指针是指针,下面我们来回顾一下之前学习过的指针都有哪些。

int* pt整形指针指向整形的指针存放整形变量的地址
float* pf浮点型指针指向浮点型的指针存放浮点型变量的地址
char* pc字符型指针指向字符型的指针存放字符型变量的地址
int (*p)[5]数组指针指向数组的指针存放数组变量的地址

int arr[5] = {1,2,3,4,5};

int (*pt)[5] = &arr;数组指针:取出的是数组的地址存放到pa中,pa是数组指针变量。

其中 int (*) [5]?是数组指针的类型。

注意:上述中的数组长度【5必须要保持一致。

&数组名vs数组名:

这里我们来回顾一下之前学习有关数组名的知识:
1.数组名是数组首元素的地址。

2.&数组名:代表的是取出整个数组的地址。

3.sizeof(数组名):计算出的是整个数组的大小。

代码展示:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", arr + 1);

	printf("%p\n", &arr[0]);
	printf("%p\n", &arr[0] + 1);

	printf("%p\n", &arr);
	printf("%p\n", &arr + 1);
	return 0;
}


代码运行结果:


解析:

?

数组指针应该怎么用??

一维数组:?

代码展示:

#define _CRT_SECURE_NO_WARNINGS 1
//一维数组
#include<stdio.h>
//采用数组来接收
void print1(int arr[], int s)
{
	int i = 0;
	for (i = 0; i < s; i++)
	{
		printf("%d ", arr[i]);
	}
}
//采用指针来接收
void print2(int* pa, int s)
{
	int i = 0;
	for (i = 0; i < s; i++)
	{
		printf("%d ", *(pa + i));
	}
}
//采用数组指针来接收
void print3(int (*pa)[10], int s)
{
	int i = 0;
	for (i = 0; i < s; i++)
	{
		printf("%d ", (*pa)[i]);
	}
}
void test1()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	print1(arr, sz);
	printf("\n");
	print2(arr, sz);
	printf("\n");
	print3(&arr, sz);//需要用数组指针来接收
}
int main()
{
	test1();
	return 0;
}


代码运行截图:

?

二维数组:?

代码展示:

#define _CRT_SECURE_NO_WARNINGS 1
//二维数组
#include<stdio.h>
//采用数组接收
void print1(int arr[3][5], int n, int m)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < m; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
//用数组指针来接收
void print2(int (*pa)[5], int n, int m)
{
	int i = 0;
	for (i = 0; i < n; i++)
	{
		int j = 0;
		for (j = 0; j < m; j++)
		{
			printf("%d ", *(*(pa + i) + j));
		}
		printf("\n");
	}
}
void test2()
{
	int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6}, {3,4,5,6,7} };
	print1(arr, 3, 5);
	printf("\n");
	print2(arr, 3, 5);
}
int main()
{
	test2();
	return 0;
}


代码运行结果:

下面我们来梳理一下数组指针和指针数组吧!

int arr[5]整型数组
int* paar[5]指针数组
int (*paar2)[5]数组指针
int (* paar3[10])[5]数组指针类型

?

?

数组参数、指针参数:

数组传参可以是数组也可以是指针。?

一维数组传参:

?二维数组传参:

一级指针传参:?

一级指针传参用一级指针接收即可。

代码展示:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void print(int *p, int s)
{
	int i = 0; 
	for (i = 0; i < s; i++)
	{
		printf("%d\n", *(p + i));
	}
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;
	int sz = sizeof(arr) / sizeof(arr[0]);
	print(p, sz);
	return 0;
}


运行结果截图:

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

二级指针传参:?

代码展示:
?

#define _CRT_SECURE_NO_WARNINGS 1
//二级指针传参
#include<stdio.h>
void test(int** ptr)
{
	printf("num = %d\n", **ptr);
}
int main()
{
	int n = 10;
	int* p = &n;
	int** pp = &p;
	test(pp);
	test(&p);
	return 0;
}

代码运行截图:

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

函数指针:?

指向函数的指针。

如何调用:
?

接下来我们来一起阅读两段代码:
(*(void (*)()0))():

?

void (*signal(int,void(*)(int)))(int):

?可以对上述声明进行类型重定义:

?这样看会起来更加便于阅读

?注意:重定义的时候不可以写为:typedef void(*)(int) pf_t;这样写是错误的写法。

?

函数指针数组:

函数指针的写法为:int(*pt)( int, int )

则函数指针数组的写法为:int (*ptArr[2])( int , int )

int (*ptArr[2])( int , int ) = {Add,Sub};

可以存放多个参数相同,返回类型相同的函数的地址。

代码展示:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int main()
{
	int (*ptArr[2])(int, int) = { Add,Sub };
	int ret = ptArr[0](2, 3);
	printf("%d\n", ret);
	ret = ptArr[1](2, 3);
	printf("%d\n", ret);
	return 0;
}


代码运行结果:

题目:写一个计算器:

代码展示:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}
void menu()
{
	printf("*****************************\n");
	printf("******* 1.Add  2.Sub  *******\n");
	printf("******* 3.Mul  4.Div  *******\n");
	printf("******* 0.exit        *******\n");
	printf("*****************************\n");
}
int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch(input)
		{
		case 1:
			printf("请输入两个操作数:>\n");
			scanf("%d %d", &x, &y);
			ret = Add(x, y);
			printf("%d\n", ret);
			break;
		case 2:
			printf("请输入两个操作数:>\n");
			scanf("%d %d", &x, &y);
			ret = Sub(x, y);
			printf("%d\n", ret);
			break;
		case 3:
			printf("请输入两个操作数:>\n");
			scanf("%d %d", &x, &y);
			ret = Mul(x, y);
			printf("%d\n", ret);
			break;
		case 4:
			printf("请输入两个操作数:>\n");
			scanf("%d %d", &x, &y);
			ret = Div(x, y);
			printf("%d\n", ret);
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择:>\n");
			break;
		}
	} while (input);
	return 0;
}


代码运行结果:

采用函数指针数组来简化代码。

简化代码展示:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}
void menu()
{
	printf("*****************************\n");
	printf("******* 1.Add  2.Sub  *******\n");
	printf("******* 3.Mul  4.Div  *******\n");
	printf("******* 0.exit        *******\n");
	printf("*****************************\n");
}
int main()
{
	int input = 0;
	int x = 0;
	int y = 0;
	int ret = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		//函数指针数组 ---- 转移表
		int (*ptArr[5])(int, int) = { 0,Add,Sub,Mul,Div };
		if (input == 0)
		{
			printf("退出游戏\n");
			break;
		}
		else if (input >= 1 && input <= 4)
		{
			printf("请输入两个操作数:>\n");
			scanf("%d %d", &x, &y);
			ret = ptArr[input](x, y);
			printf("%d\n", ret);
		}
		else
		{
			printf("输入错误,请重新输入\n");
		}
	} while (input);
	return 0;
}


代码运行结果:
?

?采用函数指针数组的优点可以大大减少代码的冗余。

指向函数指针数组的指针:

函数指针:

int (*pf)(int, int )

函数指针数组:

int (*ptArr[3])(int, int)

指向函数指针数组的指针:

int ( * (*ptr)[4] ) (int, int) = &ptArr;

回调函数:

概念:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对事件或条件进行响应。

题目:用回调函数来写计算器:

代码展示:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}
void menu()
{
	printf("*****************************\n");
	printf("******* 1.Add  2.Sub  *******\n");
	printf("******* 3.Mul  4.Div  *******\n");
	printf("******* 0.exit        *******\n");
	printf("*****************************\n");
}
void calc(int (*p)(int,int))
{
	int x = 0;
	int y = 0;
	int ret = 0;
	printf("请输入两个操作数:>\n");
	scanf("%d %d", &x, &y);
	ret = p(x, y);
	printf("%d\n", ret);
}
int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			calc(Add);
			break;
		case 2:
			calc(Sub);
			break;
		case 3:
			calc(Mul);
			break;
		case 4:
			calc(Div);
			break;
		case 0:
			printf("退出游戏\n");
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}


运行结果截图:

结束语:

这次小编和大家分享了指针进阶的相关内容,希望对大家有所帮助,下次小编将会给大家分享指针的一些具体练习,想要学习的同学记得关注小编和小编一起学习吧!如果文章中有任何错误也欢迎各位大佬及时为小编指点迷津(在此小编先谢过各位大佬啦!)

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-08-19 18:45:50  更:2022-08-19 18:48:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/10 11:06:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码