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++知识库 -> 凡人修仙学指针-2 -> 正文阅读

[C++知识库]凡人修仙学指针-2

六、指针筑基期

?

?这一节,我们将使用指针来逛妖兽交易市场,快速掌握指针的进阶用法。


目录

六、指针筑基期

6.1 指针和数组

指针作为数组来使用

数组当成指针的合法使用

数组当成指针的非法使用

数组和指针“大小”的区别

?数组名,到底是什么

6.2 指针和const

自由指针-到处乱看,暴力砍价

指向常量的指针-佛系逛黑市,只看不还价

常量指针-看准一只妖兽,只为它而来

指向常量的常指针-不差钱的专一顾客

6.3 指向数组的指针

指向数组的指针的定义和基本使用

?指向数组的指针的加减法

6.4 函数的参数传递数组

函数的参数传递一维数组

函数的参数传递二维数组(4种方式)

6.5?函数返回数组


6.1 指针和数组

指针作为数组来使用

// 修仙界黑市中,1级到8级妖兽的价格
int prices[8] = { 100, 200, 500, 800, 1000, 2000, 5000, 10000 };

int* p = &prices[0]; //prices;

for (int i = 0; i < 8; i++) {
	printf("第%d级妖兽的价格为:%d 灵石\n", i + 1, p[i]);  //用数组的形式来使用指针
}

小结:对于指针p,? ?编译器把 p[i] 理解为: *(p+i)?

数组当成指针的合法使用
?

// 修仙界黑市中,1级到8级妖兽的价格
int prices[8] = { 100, 200, 500, 800, 1000, 2000, 5000, 10000 };

*prices = 150;  // 数组以指针的使用来使用

printf("%d\n", prices[0]); // 150

数组当成指针的非法使用

// 修仙界黑市中,1级到8级妖兽的价格
int prices[8] = { 100, 200, 500, 800, 1000, 2000, 5000, 10000 };

int x;
prices = &x;  //数组名不能指向其它位置,类似于一个“特殊的常量指针”

数组和指针“大小”的区别

// 修仙界黑市中,1级到8级妖兽的价格
int prices[8] = { 100, 200, 500, 800, 1000, 2000, 5000, 10000 };

int* p = prices;

printf("%d, %d", sizeof(p), sizeof(prices)); 
// 输出 4,32 或者 8,32 
// 在32位系统中(x86), 指针占用 4个字节的内存
// 在64位系统中(x64), 指针占用 8个字节的内存

?数组名,到底是什么

// 修仙界黑市中,1级到8级妖兽的价格
int prices[8] = { 100, 200, 500, 800, 1000, 2000, 5000, 10000 };

// 1. 数组名的值,就是该数组第0个成员的地址
printf("%x, %x\n", prices, &prices[0]);

// 2. 对于数据的访问,数组名,类似于一个常量指针, 不能改变指向
// 此时,p和prices很相似
int* const p = &prices[0];  //const的用法后面会详细讲解

// 3. 对于内存大小,数组和类型又不同
printf("%d, %d", sizeof(p), sizeof(prices));

6.2 指针和const

在修仙世界的妖兽黑市,使用指针逛黑市,配合const,可以得到不同的效果。

自由指针-到处乱看,暴力砍价

// 修仙界黑市中,1级到8级妖兽的价格
int prices[8] = { 100, 200, 500, 800, 1000, 2000, 5000, 10000 };
int* p = prices;

p += 2;		// 改变指向
*p -= 100;  //强行改变价格
printf("%d\n", *p); //400  

指向常量的指针-佛系逛黑市,只看不还价

// 修仙界黑市中,1级到8级妖兽的价格
int prices[8] = { 100, 200, 500, 800, 1000, 2000, 5000, 10000 };
const int* p = prices;
	
p += 2;    //可以改变p的指向
*p -= 100; //编译失败! 不能改变指向的内容

常量指针-看准一只妖兽,只为它而来

// 修仙界黑市中,1级到8级妖兽的价格
int prices[8] = { 100, 200, 500, 800, 1000, 2000, 5000, 10000 };
int * const p = prices;

p += 2;		//编译失败!不可以改变指向
*p -= 50;	//可以砍价(可以改变指向的数据)

指向常量的常指针-不差钱的专一顾客

// 修仙界黑市中,1级到8级妖兽的价格
int prices[8] = { 100, 200, 500, 800, 1000, 2000, 5000, 10000 };
const int * const p = prices;

p += 2;		//编译失败!不可以改变指向
*p -= 50;	//编译失败!不可以砍价,不可以改变指向的数据

6.3 指向数组的指针

我们一起来分析一下各个等级的修仙者的寿命,顺便掌握指向数组的用法。

下境界?

?练气期(吸纳天地灵气,入体化为元力,寿元可达至百来岁,可短时间御剑飞行)
筑基期(丹田为液态状,可辟谷,可达两百余岁,不能遁光,能长时间御剑飞行)
金丹期(丹田内有规则的圆形固态丹元,已辟谷,寿元可达五百载,可驾遁光飞行)
元婴期(破丹成婴,寿元可达千年岁月,遁光飞行,破体元婴可瞬移)

上境界?

化神期(体内元婴倍增,元婴向元神过渡,可超两千余年,掌握元力,可破元婴瞬移)
炼虚期(寿元可达近五千岁,体内元婴化为元神,返虚出本体,化为分身或众多分身)
合体期(分身与本体合二为一,达到返朴归真,可破炼虚万千化身,寿元可达上万年载)
大乘期(可达两万余年,熟练使用或自创神通,法力肉身已具备飞升条件,谌为修士大能)

指向数组的指针的定义和基本使用

int ages[2][4] = {
	100, 200, 500,  1000,   //ages[0]  下境界中4个等级的寿命数组
	2000,5000,10000,20000   //ages[1]  上境界中4个等级的寿命数组
};

int(*p)[4]; 
//定义了一个指向数组的指针p
//p只能指向: 含有4个成员,每个成员都是int类型的数组
//注意语法,*必须在( )里面

p = &ages[0]; //ages

// 通过指向数组的指针,来访问数组内的成员
for (int i = 0; i < 4; i++) {
	printf("%d ", (*p)[i]);  // p[0][i]
}

// 指向数组的指针的大小
printf("\n %d %d \n", sizeof(p), sizeof(*p));

?指向数组的指针的加减法

int ages[2][4] = {
	100, 200, 500,  1000,   //ages[0]  下境界中4个等级的寿命数组
	2000,5000,10000,20000   //ages[1]  上境界中4个等级的寿命数组
};

int(*p)[4] = &ages[0]; //ages

p++; // p指向了下一个数组!
printf("%d\n", (unsigned int)(p + 1) - (unsigned int)p); //16

for (int i = 0; i < 4; i++) {
	printf("%d ", (*p)[i]);  // 2000
}

6.4 函数的参数传递数组

函数的参数传递一维数组

计算1-8级妖兽的平均价格。

#include <stdio.h>

int calcAveragePrice1(int p[8]) {
	// 特别注意:此时 p 不是真正的数组,实际上是一个指针 int *p
	printf("%d\n", sizeof(p));

	int s = 0;
	for (int i = 0; i < 4; i++) {
		s += p[i];
	}
	return s / 4;
}

int calcAveragePrice2(int p[], int n) {
	int s = 0;
	for (int i = 0; i < 4; i++) {
		s += p[i];
	}
	return s / 4;
}

int calcAveragePrice3(int *p, int n) {
	int s = 0;
	for (int i = 0; i < 4; i++) {
		s += p[i];
	}
	return s / 4;
}

int main(void) {
	// 修仙界黑市中,1级到8级妖兽的价格
	int prices[8] = { 100, 200, 500, 800, 1000, 2000, 5000, 10000 };
	
	// 计算1-8级妖兽的平均价格
	printf("%d\n", calcAveragePrice1(prices)); //ages;
	printf("%d\n", calcAveragePrice2(prices, 8)); //ages;
	printf("%d\n", calcAveragePrice2(prices, 8)); //ages;

	return 0;
}

函数的参数传递二维数组(4种方式)

计算各阶修士的平均寿命。

#include <stdio.h>

int calcAverageAge1(int ages[2][4]) {
	// 特别注意:此时 ages 不是真正的二维数组
	// 实际上是一个指向一维数组的指针 int (*ages)[4]
	printf("%d\n", sizeof(*ages));

	int s = 0;
	for (int i = 0; i < 2; i++) {
		for (int j = 0; j < 4; j++) {
			s += ages[i][j];
		}
	}

	return s / (2 * 4);
}

int calcAverageAge2(int ages[][4], int n) {
	// 特别注意:此时ages 不是真正的数组
	// 实际上是一个指向一维数组的指针 int (*ages)[4]
	printf("%d\n", sizeof(*ages));

	int s = 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < 4; j++) {
			s += ages[i][j]; // *(*(ages+i) + j)
		}
	}

	return s / (2 * 4);
}


int calcAverageAge3(int(*ages)[4], int n) {
	printf("%d\n", sizeof(*ages));

	int s = 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < 4; j++) {
			s += ages[i][j]; // *(*(ages+i) + j)
		}
	}

	return s / (2 * 4);
}

int calcAverageAge4(int* ages, int m, int n) {
	int s = 0;
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			s += *(ages + i * n + j);
		}
	}

	return s / (2 * 4);
}

int main(void) {
	int ages[2][4] = {
		100, 200, 500,  1000,   //ages[0]  下境界中4个等级的寿命数组
		2000,5000,10000,20000   //ages[1]  上境界中4个等级的寿命数组
	};

	printf("%d\n", calcAverageAge1(ages));
	printf("%d\n", calcAverageAge2(ages, 2));
	printf("%d\n", calcAverageAge3(ages, 2));
	printf("%d\n", calcAverageAge4(ages, 2, 4));
	return;
}

“C语言以及C++中,不能直接把二维数组(或更多维数组),作为一般形式的函数参数,你无法向函数传递一个普通的多维数组。” 引用自《C专家编程》第10章的第5节。

但是我们可以使用以上示例代码中4种形式来传递二维数组。

6.5?函数返回数组

定义一个函数,进行计算,返回一个数组,数组中包含各级妖兽的最低价格和最高价格,以及平均价格。

int(*calc(int prices[], int n))[3]{
	int s = 0;
	for (int i = 0; i < n; i++) {
		s += prices[i];
	}

	int(*ret)[3]; // 定义一个指向数组的指针
	ret = malloc(3 * sizeof(int));
	(*ret)[0] = prices[0];
	(*ret)[1] = prices[n - 1];
	(*ret)[2] = s / n;
	return ret;
}

int main(void) {
	// 修仙界黑市中,1级到8级妖兽的价格
	int prices[8] = { 100, 200, 500, 800, 1000, 2000, 5000, 10000 };
	int(*p)[3] = calc(prices, 8);

	printf("最低价格=%d, 最高价格=%d, 平均价格=%d", (*p)[0], (*p)[1], (*p)[2]);
	
	return;
}

使用typedef 对指向数组的指针,进行优化:

typedef int(*threeValueArray_t)[3];

threeValueArray_t calc(int prices[], int n){
	int s = 0;
	for (int i = 0; i < n; i++) {
		s += prices[i];
	}

	int(*ret)[3]; // 定义一个指向数组的指针
	ret = malloc(3 * sizeof(int));
	(*ret)[0] = prices[0];
	(*ret)[1] = prices[n - 1];
	(*ret)[2] = s / n;
	return ret;
}

int main(void) {
	// 修仙界黑市中,1级到8级妖兽的价格
	int prices[8] = { 100, 200, 500, 800, 1000, 2000, 5000, 10000 };
	threeValueArray_t p = calc(prices, 8);

	printf("最低价格=%d, 最高价格=%d, 平均价格=%d", (*p)[0], (*p)[1], (*p)[2]);
	
	return;
}

至此,我们以及掌握了指针的筑基期用法,马上将要进阶金丹期!

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

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