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/C++指针详解(附例题) -> 正文阅读

[C++知识库]C/C++指针详解(附例题)

什么是指针

我们口头中的指针又称为指针变量,指针变量存储的是地址。

在深入了解指针前首先要认识两个符号

*(解引用操作符)和&(取地址操作符)

*(解引用操作符)常常使用在指针变量之前,表示取得指针指向的值

&(取地址操作符)取某变量的地址

下面举一个例子

int main() {
	int num = 0;
	int* a = #
//我写的时候经常忘加&
	return 0;
}

&num表示取得num变量的地址

int * a 表示声明一个名称为a的int * 类型的指针变量

int * a = & num 表示将num 的地址赋予a 这个指针变量?

可以通过监视来验证我们的想法?

?a是表明&num的变量,那&a呢?

&a是二级指针,二级指针指的是存储一级指针变量的地址的变量。也就是通常所说的“指针的指针”

int main() {
	int num = 0;
	int* a = #
	int** pa = &a;
	return 0;
}

验证

?

指针与数组

数组名即为指针

一维数组

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

?一维数组名(arr) 表示 首元素

在一般情况下,?一维数组名(arr) 的地址表示首元素的地址。

但是在sizeof(数组名)和 & 数组名 两种情况下数组名表示整个数组的地址

例题

int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));
//4*4=16
printf("%d\n",sizeof(a+0));
//表示首元素大小 4
printf("%d\n",sizeof(*a));
//*a对数组名进行解引用 得到一个int型数据(1) 4
printf("%d\n",sizeof(a+1));
//a+1表示第二个元素(2) 4
printf("%d\n",sizeof(a[1]));
//a[1]表示第二个元素(2) 4
printf("%d\n",sizeof(&a));
//&a表示取出整个数组的地址 还是个地址 地址大小为4或8
printf("%d\n",sizeof(*&a));
//*&同时出现等于什么都没变  同sizeof(a) 大小为16
printf("%d\n",sizeof(&a+1));
//跳过整个数组 来到下一个同等大小的数组的首元素位置 16
printf("%d\n",sizeof(&a[0]));
//加了&就是地址 地址统统为4或8个字节!
printf("%d\n",sizeof(&a[0]+1));
//地址+1=移动一个int型的位置 来到(2)的位置 sizeof(int)=4

二维数组

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

二维数组存储的逻辑结构

?二维数组的物理结构则是连续的空间

?二维数组的数组名(d)是首元素的地址,二维数组的首元素是第一行(一维数组)

?在本题中 d [ 0 ] 则表示一维数组的数组名,即一维数组首元素 d [ 0 ] [ 0 ]

例题(博主以前经常写错)

int a[3][4] = {0};
printf("%d\n",sizeof(a));
//3*4*4=48
printf("%d\n",sizeof(a[0][0]));
//首元素 4 
printf("%d\n",sizeof(a[0]));
//4+4+4+4=16
//a[0]是第一行这个一维数组的数组名,单独放在sizeof内部,a[0]表示第一个整个这个一维数组
//sizeof(a[0])计算的就是第一行的大小
printf("%d\n",sizeof(a[0]+1));
//a[0]并没有单独放在sizeof内部,也没取地址,a[0]就表示首元素的地址
//就是第一行这个一维数组的第一个元素的地址,a[0] + 1就是第一行第二个元素的地址
printf("%d\n",sizeof(*(a[0]+1)));
//a[0] + 1就是第一行第二个元素的地址
//*(a[0] + 1))就是第一行第二个元素
printf("%d\n",sizeof(a+1));
//4或8
//这个题我不知道错了多少遍了已经
	//a虽然是二维数组的地址,但是并没有单独放在sizeof内部,也没取地址
	//a表示首元素的地址,二维数组的首元素是它的第一行,a就是第一行的地址
	//a+1就是跳过第一行,表示第二行的地址
printf("%d\n",sizeof(*(a+1)));
//16
	//*(a + 1)是对第二行地址的解引用,拿到的是第二行
	//*(a+1)-->a[1]
	//sizeof(*(a+1))-->sizeof(a[1])

printf("%d\n",sizeof(&a[0]+1));
//4或8
//第二行的地址
printf("%d\n",sizeof(*(&a[0]+1)));
//16
//第二行的大小
printf("%d\n",sizeof(*a));
//16
	//a表示首元素的地址,就是第一行的地址
	//*a就是对第一行地址的解引用,拿到的就是第一行
printf("%d\n",sizeof(a[3]));
//16
//第4行的大小
//虽然越界了但是sizeof可不管内容

?

指针的类型

比较普通的类型

	char ch = 'a';
	char* b = &ch;
	int num = 0;
	int* a = #
	double dou = 3.14;
	double* c = &dou;

直接在类型后添上一个*就是一个类型。

进阶版

指针数组

指针数组首先得是一个数组,数组里每个元素都是一个指针

int * a1;
int * a2;
int * a3;
int * a4;
int * arr[4]={a1,a2,a3,a4};

arr首先于 [ ] 结合,成为一个有四个指针变量的数组

?其实,对于指针数组,去掉数组名和后面的方括号,剩下的就是数组中存储元素的类型

数组指针

数组指针,首先是个指针,指针指向一个数组

int arr1[4] ={1,2,3,4};
int (*p) [4] = arr1 ;

必须将 * 与 p 用小括号括起来

?必须将 * 与 p 用小括号括起来

( * p ) 其实就== arr

( * p )是arr 的引用

函数指针

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

int (*padd)(int, int) = Add;

函数指针数组

int (*pf[5]) (int, int) = { 0,Add,Sub ,Div ,Sum };

回调函数

什么是回调函数?回调函数就是通过函数指针调用的函数,比如上面的pf指针,它调用的Add,Sub ,Div ,Sum被称为回调函数

计算器实例

第一种方式,函数指针传参

在使用时直接调用calc函数即可

//写一个计算器

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

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

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

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

//第一种方式,函数指针传参
void calc(int(*pf)(int, int)) {
	int x=0;
	int y=0;
	printf("please inter two numbers");
	scanf("%d %d", &x, &y);

	int num=pf(x, y);
	printf("%d", num);
}

第二种:函数指针数组

	int (*pf[5]) (int, int) = { 0,Add,Sub ,Div ,Sum };
	
	int input = 0;
		do {
			printf("please make operation \n");
			scanf("%d", &input);
			if (input == 0)
			{
                //退出计算器
				printf("thank you !!!\n" );
				break;
			}
			else if (input > 0 && input < 5) {
                //开始计算,首先输入待计算的数字
				int x = 0;
				int y = 0;
				printf("please inter two numbers\n");
				scanf("%d %d", &x, &y);
                //调用函数
				int res=pf[input](x, y);
				printf("%d\n", res);
			}
			else {
				printf("please enter right number\n");
			}

		} while (input);

qsort实例

指针的运算

+- 移动的距离和指针解引用后表示的数据类型有关

普通指针+-数字

int b =1;
int * pb = &b;
pb+1 == ???

pb + 1 表示移动sizeof(int ) 大小的步长

在本题中移动四个字节的大小

若pb=0x00000001

pb+1=0x00000005

char c= ' c ';
char * pc = &c;
pc+1 == ???

若pc=0x00000001

pc+1=0x00000002

数组名+-数字

这里注意,只要不是sizeof(数组名)或&数组名,其他情况下数组名==首元素

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-11-05 00:06:35  更:2022-11-05 00:08:06 
 
开发: 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/19 6:03:09-

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