2021-02-25-C++学习之5

一、指针
1. 基本概念
作用:通过指针间接访问内存
- 内存编号是从0开始记录的,一般用十六进制数字表示
- 可以利用指针变量保存地址
2. 定义与使用
语法:数据类型 * 指针变量名;

#include<iostream>
using namespace std;

int main()
{
	int a = 10;
	//指针定义
	int * p;
	p = &a;
	cout << "a的地址为:" << &a << endl;
	cout << "指针p为:" << p << endl;
	//指针使用
	//指针前加 * 代表解引用,找到指针指向的内存中的数据
	*p = 1000;
	cout << "a = " << a << endl;
	cout << "*p = " << *p << endl;
	system("pause");
	return 0;
}

打印结果为:

a的地址为:00EFFAF4
指针p为:00EFFAF4
a = 1000
*p = 1000
请按任意键继续. . .

3. 指针所占内存空间
在32位操作系统下占4个字节,64位下占8个字节
代码:

#include<iostream>
using namespace std;
int main()
{
	int a = 10;
	//在32位操作系统下占4个字节,64位下占8个字节,不管是什么数据类型
	int* p = &a;
	cout << "sizeof(int *) = " << sizeof(int *) << endl;
	cout << "sizeof(float *) = " << sizeof(float *) << endl;
	cout << "sizeof(double *) = " << sizeof(double *) << endl;
	cout << "sizeof(char *) = " << sizeof(char *) << endl;
	
	system("pause");
	return 0;
}

打印结果:

sizeof(int *) = 4
sizeof(float *) = 4
sizeof(double *) = 4
sizeof(char *) = 4
请按任意键继续. . .

4. 空指针
指针变量指向内存中编号为0的空间
用于初始化指针变量
注意:空指针指向的内存是不可以访问的
代码:

#include<iostream>
using namespace std;

int main()
{
	//空指针用于给指针变量进行初始化
	int* p = NULL;

	//空指针不可以进行访问
	// 0~255之间的内存编号是系统占用的,因此不可以访问
	//*p = 100;  //错误,引发一个异常
	//cout << *p << endl;  //错误,引发一个异常
	system("pause");
	return 0;
}

5. 野指针
指针变量指向非法的内存空间
代码:

#include<iostream>
using namespace std;

int main()
{
	//在程序中,尽量避免出现野指针
	//int* p = (int*)0x1100;
	//cout << *p << endl;  //引发异常
	system("pause");
	return 0;
}

空指针和野指针都不是我们申请的空间,因此不能访问。
6. const修饰指针

  • const修饰指针 --常量指针
//常量指针,指针的指向可以修改,但指针指向的值不可以改
	const int * p = &;   
	*p = 20;   //错误,指针指向的值不可以更改
	 p = &b;   //正确,指针的指向可以改
  • const修饰常量 --指针常量
//指针常量,特点:指针的指向不可以改,指针指向的值可以改
int * const p = &a; 
*p = 20;  //正确,指针的值可以改
p = &b;  //错误,指针的指向不可以改
//记忆技巧:const直接作用于p,则p不能修改
  • const既修饰指针,又修饰常量
//特点:指针的指向和指针指向的值都不可以改
const int * const p = &a;
*p = 20;  //错误,指针指向的值不可以更改
p = &b;  //错误,指针的指向不可以改

7. 指针和数组
利用指针访问数组中元素
代码:

#include<iostream>
using namespace std;

int main()
{
	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
	cout << "第一个元素为:" << arr[0] << endl;
	int * p = arr; //arr是数组首地址
	cout << "利用指针访问第一个元素:" << *p << endl;
	p++; //让指针向后偏移4个字节
	cout << "利用指针访问第二个元素:" << *p << endl;
	cout << "利用指针遍历数组" << endl;
	int* p2 = arr;
	for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++)
	{
		cout << *p2 << endl;
		p2++;
	}
	system("pause");
	return 0;
}

打印结果:

第一个元素为:1
利用指针访问第一个元素:1
利用指针访问第二个元素:2
利用指针遍历数组
1
2
3
4
5
6
7
8
9
10
请按任意键继续. . .

8. 指针和函数
利用指针作为函数参数,可以修改实参的值
代码:

#include<iostream>
using namespace std;

//实现两个数字进行交换
//值传递
void swap01(int a, int b)
{
	int temp = a;
	a = b;
	b = temp;
	cout << "swap01 a = " << a << endl;
	cout << "swap01 b = " << b << endl;
}
//地址传递
void swap02(int *p1, int *p2)
{
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}

int main()
{
	int a = 10;
	int b = 20;
	cout << "交换前:" << endl;
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	//swap01(a, b);
	swap02(&a,&b);
	cout << "交换后:" << endl;
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;

	system("pause");
	return 0;
}

打印结果:

交换前:
a = 10
b = 20
交换后:
a = 20
b = 10
请按任意键继续. . .

地址传递原理:
在这里插入图片描述
在这里插入图片描述
9. 指针、数组、函数
案例描述:封装一个函数,利用冒泡排序,实现对整型数组的升序排序。
代码:

#include<iostream>
using namespace std;

//冒泡排序
void bubbleSort(int *arr, int len)
{
	for (int i = 0; i < len - 1; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
}
//打印
void printArray(int* arr, int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << arr[i] << "  ";
	}
	cout << endl;
}
int main()
{
	int arr[10] = {4, 3, 6, 9, 1, 2, 10, 8, 7, 5 };
	int len = sizeof(arr) / sizeof(arr[0]);
	cout << "排序前:" << endl;
	printArray(arr, len);
	bubbleSort(arr, len);
	cout << "排序后:" << endl;
	printArray(arr, len);
	system("pause");
	return 0;
}

打印结果:

排序前:
4  3  6  9  1  2  10  8  7  5
排序后:
1  2  3  4  5  6  7  8  9  10
请按任意键继续. . .

二、结构体
1. 概念
结构体属于用户自定义的数据类型,允许用户存储不同的数据类型
2. 定义与使用

  • 语法:struct 结构体名 { 结构体成员列表 };
    通过结构体创建变量的方式有三种:
    • struct 结构体名 变量名
    • struct 结构体名 变量名 = { 成员1值,成员2值 }
    • 定义结构体时顺便创建变量
      注意:结构体变量创建时,struct关键字可以省略;但是定义结构体时,struct关键字不能省略;结构体变量用操作符“ . ”访问成员
      代码:
#include<iostream>
using namespace std;
#include<string>

struct Student
{
	string name;
	int age;
	int score;
}s3; //创建结构体变量第三种方法,顺便创建结构体变量

int main()
{
	//结构体变量创建时,struct关键字可以省略
	//但是定义结构体时,struct关键字不能省略
	//创建结构体变量第一种方法
	struct Student s1;
	//给s1属性赋值,通过 . 访问结构体变量中的属性
	s1.name = "张三";
	s1.age = 18;
	s1.score = 100;
	cout << "姓名:" << s1.name << "  年龄: " << s1.age << "  分数:" << s1.score << endl;
	
	//创建结构体变量第二种方法
	 Student s2 = {"李四", 19, 80};
	cout << "姓名:" << s2.name << "  年龄: " << s2.age << "  分数:" << s2.score << endl;
	
	//创建结构体变量第三种方法
	s3.name = "王五";
	s3.age = 20;
	s3.score = 60;
	cout << "姓名:" << s3.name << "  年龄: " << s3.age << "  分数:" << s3.score << endl;


	system("pause");
	return 0;
}

打印结果:

姓名:张三  年龄: 18  分数:100
姓名:李四  年龄: 19  分数:80
姓名:王五  年龄: 20  分数:60
请按任意键继续. . .

3. 结构体数组
作用:将自定义的结构体放入数组中方便维护
语法:struct 结构体名 数组名{ 元素个数 } = {{},{},... {}}
代码:

#include<iostream>
using namespace std;
#include<string>

struct Student
{
	string name;
	int age;
	int score;
}; 

int main()
{
	//创建结构体数组
	struct Student stuArray[3] =
	{
		{"张三", 18, 100},
		{"李四", 28, 99},
		{"王五", 38, 66}
	};
	//给结构体数组中的元素赋值
	stuArray[2].name = "赵六";
	stuArray[2].age = 80;
	stuArray[2].score = 60;
	//遍历结构体数组
	for (int i = 0; i < 3; i++)
	{
		cout << "姓名:" << stuArray[i].name << "; 年龄:" << stuArray[i].age << "; 分数:" << stuArray[i].score << endl;
	}
	return 0;
}

打印结果:

姓名:张三; 年龄:18; 分数:100
姓名:李四; 年龄:28; 分数:99
姓名:赵六; 年龄:80; 分数:60

4. 结构体指针
通过指针访问结构体中的成员

  • 利用操作符 ->可以通过结构体指针访问结构体属性
    代码:
#include<iostream>
using namespace std;
#include<string>

struct Student
{
	string name;
	int age;
	int score;
}; 

int main()
{
	//创建结构体数组
	Student s =	{ "张三", 18, 100 };
	//通过指针指向结构体变量
	Student * p = &s;
	//通过指针访问结构体变量中的数据
	//通过结构体指针访问结构体中的属性,需要利用'->'
	cout << "姓名:" << p->name << "; 年龄:" << p->age << "; 分数:" << p->score << endl;

	system("pause");
	return 0;
}

打印结果:

姓名:张三; 年龄:18; 分数:100
请按任意键继续. . .

5. 结构体嵌套结构体
作用:结构体中的成员可以是另一个结构体
如:每个老师辅导一个学生,一个老师的结构体中,记录一个学生的结构体。

代码:
#include<iostream>
using namespace std;
#include<string>

struct Student
{
	string name = " ";
	int age = 18;
	int score = 0;
};

struct Teacher
{
	int id = 0;
	string name = " ";
	int age = 0;
	struct Student stu = {" ", 0, 0};
};

int main()
{
	Teacher t;
	t.id = 10000;
	t.name = "老王";
	t.age = 50;
	t.stu.name = "小王";
	t.stu.age = 20;
	t.stu.score = 60;

	cout << "老师姓名:" << t.name << "; 老师编号:" << t.id << "; 老师年龄:" << t.age << endl
	<< "老师辅导的学生姓名:" <<t.stu.name << "; 学生年龄:" << t.stu.age << "; 学生考试分数:" << t.stu.score << endl;

	system("pause");
	return 0;
}

打印结果:

老师姓名:老王; 老师编号:10000; 老师年龄:50
老师辅导的学生姓名:小王; 学生年龄:20; 学生考试分数:60
请按任意键继续. . .

6. 结构体做函数参数
将结构体作为参数向函数中传递
传递方式:值传递;地址传递
代码:

#include<iostream>
using namespace std;
#include<string>

struct Student
{
	string name = " ";
	int age = 18;
	int score = 0;
};
//值传递
void printStudent1(struct Student s)
{
	s.age = 100;
	cout << "子函数printStudent1中  姓名:" << s.name << "; 年龄:" << s.age << "; 分数:" << s.score << endl;
}
//地址传递
void printStudent2(struct Student * p)
{
	p->age = 200;
	cout << "子函数printStudent2中  姓名:" << p->name << "; 年龄:" << p->age << "; 分数:" << p->score << endl;
}
int main()
{
	Student s;
	s.name = "张三";
	s.age = 20;
	s.score = 80;
	printStudent1(s);
	cout << "main函数中打印  姓名:" << s.name << "; 年龄:" << s.age << "; 分数:" << s.score << endl;

	printStudent2(&s);
	cout << "main函数中打印  姓名:" << s.name << "; 年龄:" << s.age << "; 分数:" << s.score << endl;

	system("pause");
	return 0;
}

打印结果:

子函数printStudent1中  姓名:张三; 年龄:100; 分数:80
main函数中打印  姓名:张三; 年龄:20; 分数:80
子函数printStudent2中  姓名:张三; 年龄:200; 分数:80
main函数中打印  姓名:张三; 年龄:200; 分数:80
请按任意键继续. . .

7. 结构体中const使用场景
用const防止误操作
在这里插入图片描述
代码:

#include<iostream>
using namespace std;
#include<string>

struct Student
{
	string name = " ";
	int age = 18;
	int score = 0;
};
//将函数中的形参改为指针,可以减少内存空间,而且不会复制新的副本出来
void printStudent(const Student *s)
{
	//s->age = 150; //加入const之后,一旦有修改的操作就会报错,可以防止误操作
	cout << "姓名:" << s->name << "  年龄:" << s->age << "  分数:" << s->score << endl;
}
int main()
{
	struct Student s = {"张三", 15, 70};
	printStudent(&s);
	cout << "main函数中  姓名:" << s.name << "  年龄:" << s.age << "  分数:" << s.score << endl;

	system("pause");
	return 0;
}

打印结果:

姓名:张三  年龄:15  分数:70
main函数中  姓名:张三  年龄:15  分数:70
请按任意键继续. . .
  1. 案例
    在这里插入图片描述
    代码:
#include<iostream>
using namespace std;
#include<string>

struct Hero
{
	string name = " ";
	int age = 0;
	string sex = " ";
};
void bubbleSort(Hero heroArray[], int len)
{
	for (int i = 0; i < len - 1; i++)
	{
		for (int j = 0; j < len - i - 1; j++)
		{
			if (heroArray[j].age > heroArray[j + 1].age)
			{
				Hero temp = heroArray[j];  //注意temp是结构体Hero数据类型
				heroArray[j] = heroArray[j + 1];
				heroArray[j + 1] = temp;
			}
		}
	}
}
void printHero(Hero heroArray[], int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << "姓名: " << heroArray[i].age << "  年龄:" << heroArray[i].age
			<< "  性别:" << heroArray[i].sex << endl;
	}
}

int main()
{
	Hero heroArray[5] =
	{
		{"刘备", 23, "男"},
		{"关羽", 22, "男"},
		{"张飞", 20, "男"},
		{"赵云", 21, "男"},
		{"貂蝉", 19, "女"}
	};
	int len = sizeof(heroArray) / sizeof(heroArray[0]);
	cout << "冒泡排序前:" << endl;
	//ctrl + shift + /  是多行注释
	for (int i = 0; i < len; i++)
	{
		cout << "姓名: " << heroArray[i].age << "  年龄:" << heroArray[i].age
			<< "  性别:" << heroArray[i].sex << endl;
	}

	bubbleSort(heroArray,len);
	cout << "冒泡排序后:" << endl;
	printHero(heroArray, len);
	system("pause");
	return 0;
}

打印结果:

冒泡排序前:
姓名: 23  年龄:23  性别:男
姓名: 22  年龄:22  性别:男
姓名: 20  年龄:20  性别:男
姓名: 21  年龄:21  性别:男
姓名: 19  年龄:19  性别:女
冒泡排序后:
姓名: 19  年龄:19  性别:女
姓名: 20  年龄:20  性别:男
姓名: 21  年龄:21  性别:男
姓名: 22  年龄:22  性别:男
姓名: 23  年龄:23  性别:男
请按任意键继续. . .
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力学习的代码小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值