当前位置:网站首页>凡人修仙学指针-2
凡人修仙学指针-2
2022-07-06 09:19:00 【程序员Rock】
六、指针筑基期
这一节,我们将使用指针来逛妖兽交易市场,快速掌握指针的进阶用法。
目录
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;
}
至此,我们以及掌握了指针的筑基期用法,马上将要进阶金丹期!
边栏推荐
- View UI Plus 发布 1.1.0 版本,支持 SSR、支持 Nuxt、增加 TS 声明文件
- Counter attack of flour dregs: redis series 52 questions, 30000 words + 80 pictures in detail.
- 面渣逆袭:Redis连环五十二问,三万字+八十图详解。
- 抽象类和接口
- Fgui project packaging and Publishing & importing unity & the way to display the UI
- 系统设计学习(三)Design Amazon‘s sales rank by category feature
- 架构师怎样绘制系统架构蓝图?
- 【话题终结者】
- View UI plus released version 1.2.0 and added image, skeleton and typography components
- GNSS positioning accuracy index calculation
猜你喜欢
阿里云微服务(四) Service Mesh综述以及实例Istio
String class
TYUT太原理工大学2022数据库题库选择题总结
Novatel board oem617d configuration step record
面渣逆袭:Redis连环五十二问,三万字+八十图详解。
How do architects draw system architecture blueprints?
Tyut Taiyuan University of technology 2022 "Mao Gai" must be recited
TYUT太原理工大学2022数据库大题之分解关系模式
如何保障 MySQL 和 Redis 的数据一致性?
Answer to "software testing" exercise: Chapter 1
随机推荐
Error: sorting and subscript out of bounds
记录:newInstance()过时的代替方法
Alibaba cloud microservices (I) service registry Nacos, rest template and feign client
System design learning (III) design Amazon's sales rank by category feature
Database operation of tyut Taiyuan University of technology 2022 database
[algorithm] sword finger offer2 golang interview question 13: sum of numbers of two-dimensional submatrix
Record: I accidentally wrote a recursion next time
13 power map
TYUT太原理工大学2022“mao gai”必背
初识C语言(上)
记录:Navicat Premium初次无法连接数据库MySQL之解决
167. Sum of two numbers II - input ordered array - Double pointers
抽象类和接口
Alibaba cloud microservices (III) sentinel open source flow control fuse degradation component
How do architects draw system architecture blueprints?
Alibaba cloud side: underlying details in concurrent scenarios - pseudo sharing
十分鐘徹底掌握緩存擊穿、緩存穿透、緩存雪崩
《软件测试》习题答案:第一章
Small exercise of library management system
Share a website to improve your Aesthetics