
指针变量定义语法:
数据类型 * 变量名;指针就是地址
指针变量和普通变量的区别
要点
*p = 1000,通过*p修改内存或者访问内存总结
//p保存的是一个地址
//利用指针来保存地址,指针就是一个地址
#include
using namespace std;
int main()
{
//1.定义指针
int a = 10;
//指针定义的语法:数据类型 * 指针变量名
int* p;
//让指针记录变量a的地址,打印结果一样
p = &a; //a的地址存放在变量p中
cout << "a的地址:" << &a << endl;
cout << "指针p为:" << p << endl; //p记录a的地址
//2.使用指针
//可以通过“解引用”的方式找到指针指向的内存
//指针前加*号代表解引用,找到指针指向的内存中的数据
*p = 1000; //通过*p修改内存或者访问内存
cout << "a = " << a << endl;
cout << "*p = " << *p << endl;
system("pause");
return 0;
}
运行结果


#include
using namespace std;
int main()
{
//指针占用的空间大小
int a = 10;
//int* p;
//p = &a;//指针指向数据a的地址
int* p = &a;//等价于int* p; p = &a;
//在32位操作系统下,指针占4个字节空间大小,不管是什么数据类型
//在64位操作系统下,指针占8个字节空间大小
cout << "sizeof(int*) = " << sizeof(int*) << endl; //sizeof(p) 4
cout << "sizeof(float*) = " << sizeof(float*) << endl;
cout << "sizeof(double*) = " << sizeof(double*) << endl;
cout << "sizeof(char*) = " << sizeof(char*) << endl;
system("pause");
return 0;
}

刚开始不知道指针该指向哪里,初始化有地方可指,后期有地方可指应该重新更改指向。
#include
using namespace std;
int main()
{
//空指针
//1.空指针用于给指针变量进行初始化
int* p = NULL;//0是空指针的地址编号
//2.空指针是不可以进行访问
//0~255之间的内存编号是系统占用的,因此不可以访问
//*p = 100;//会报错
system("pause");
return 0;
}
#include
using namespace std;
int main()
{
//野指针:指针变量指向非法的内存空间
//程序中,尽量避免野指针
//指针变量p指向内存地址编号为0x1100的空间
int* p = (int*)0x1100;
//访问野指针报错
cout << *p << endl;
system("pause");
return 0;
}



#include
using namespace std;
int main()
{
int a = 10;
int b = 10;
//1.const修饰指针——常量指针,常量就是const
const int* p = &a;//特点:指针的指向可以修改,但指针指向的值不可以修改
//*p = 20; 错误
p = &b;//正确
//2.const修饰常量——指针常量
//特点:指针的指向不可以修改,指针指向的值可以修改
int* const p1 = &a;//const后面跟着常量
*p1 = 20;//正确
//p = &b;//错误,指针指向不可改
//3.const既修饰指针,又修饰常量
const int* const p2 = &a;//特点:指针的指向和指针指向的值都不可以改
system("pause");
return 0;
}
int* p = arr; 数组名arr就是数组的首地址
#include
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 < 10; i++)
{
//cout << arr[i] << endl;
cout << *p2 << " ";//p2指的是数组地址,*p2指向地址所在的值
p2++;
}
cout << endl;
system("pause");
return 0;
}


#include
using namespace std;
//实现两个数字进行交换
void swap01(int a, int b)// 形参a,b发生改变,实参没有改变
{
int temp = a;//temp保存的是a的值
a = b;
b = temp;
cout << "swap01 a = " << a << endl;
cout << "swap01 b = " << b << endl;
}
void swap02(int* p1, int* p2)
{
//temp保存的是a的值10,*p1保存的是变量a的地址,*p2保存的是变量b的地址
int temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int main()
{
//指针和函数
//1.值传递(形参改变不了实参)
int a1 = 10;
int b1 = 20;
swap01(a1, b1);
cout << "a1 = " << a1 << endl;
cout << "b1 = " << b1 << endl;
cout << endl;
//2.地址传递(形参改变实参)
//地址传递可以修饰实参
int a2 = 10;
int b2 = 20;
swap02(&a2, &b2);// p1和p2都要传递地址
cout << "a2 = " << a2 << endl;
cout << "b2 = " << b2 << endl;
system("pause");
return 0;
}

案例描述:封装一个函数,利用冒泡排序,实现对整型数组的升序排序
例如数组:int arr[10] = { 4,3,6,9,1,2,10,8,7,5 }
超级重点:
非常重要的结论如下
#include
using namespace std;
//冒泡排序函数 参数1 数组的首地址 参数2 数组的长度
void bubbleSort(int* p, int len) // arr表示数组的首地址,len是数组的长度
{
for (int i = 0; i < len - 1; i++) //p本质是一个数组,int* p表示数组第一个元素
{
for (int j = 0; j < len - i - 1; j++)
{
//如果j > j+1的值,交换数字
if (p[j] > p[j + 1])
{
int temp = p[j];
p[j] = p[j + 1];
p[j + 1] = temp;
}
}
}
}
//打印数组
void printArray(int* q, int len)// 传入的是数组的首地址以及数组长度
{
for (int i = 0; i < len; i++)//q本质是一个数组,int* q表示数组第一个元素
{
cout << q[i] << " ";
}
cout << endl;
}
int main()
{
//1.先创建一个数组
int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
//数组长度
int len = sizeof(arr) / sizeof(arr[0]);
//2.创建函数,实现冒泡排序(传入数组及其长度)
bubbleSort(arr, len);// arr就是数组的地址
//3.打印排序后的数组
printArray(arr, len);
system("pause");
return 0;
}
语法:struct 结构体名 { 结构体成员列表 };最后一定要加封号
通过结构体创建变量的方式有三种:
总结
#include
#include
using namespace std;
//1.创建学生数据类型——学生包括(姓名、年龄、分数)
//自定义数据类型,一些类型集合组成的一个类型
//语法 struct 类型名称 {成员列表}
struct Student
{
//姓名
string name;
//年龄
int age;
//分数
int score;
}s3; //创建结构体时顺便创建变量
//2.通过学生类型创建具体的学生(三种创建方式)
int main()
{
//2.1 struct Student s1
//结构体创建时struct关键字可以省略,结构体定义时struct关键字不可以省略
struct Student s1;
// Student s1;这样创建也是可以的
//给s1属性赋值,通过“.”访问结构体变量中的属性
s1.name = "张三";
s1.age = 18;
s1.score = 100;
cout << "姓名:" << s1.name << " 年龄:" << s1.age << " 分数:" << s1.score << endl;
//2.2 struct Student s2={...}
struct Student s2 = { "李四",19,80 };
cout << "姓名:" << s2.name << " 年龄:" << s2.age << " 分数:" << s2.score << endl;
//2.3 定义结构体时顺便创建结构体变量
s3.name = "王五";
s3.age = 20;
s3.score = 80;
cout << "姓名:" << s3.name << " 年龄:" << s3.age << " 分数:" << s3.score << endl;
system("pause");
return 0;
}
结果

struct 结构体名 数组名[元素个数] = { {} , {} , ... {} }#include
#include
using namespace std;
//结构体数组
//1.定义结构体
struct Student
{
//成员变量
string name;//姓名
int age;//年龄
int score;//分数
};
int main()
{
//2.创建结构体数组
//类似于struct Student s2={"李四",19,80}
struct Student stuArray[3] =
{
{"张三",18,100},
{"李四",28,99},
{"王五",38,66}
};
//3.给结构体数组中的元素赋值,将王五的信息覆盖
stuArray[2].name = "赵六";
stuArray[2].age = 80;
stuArray[2].score = 60;
//4.遍历结构体数组
for (int i = 0; i < 3; i++)
{
cout << "姓名:" << stuArray[i].name << " "
<< "年龄:" << stuArray[i].age << " "
<< "分数:" << stuArray[i].score << endl;
}
system("pause");
return 0;
}

-> 可以通过结构体指针访问结构体属性#include
#include
using namespace std;
//结构体指针
//通过指针访问结构体中的成员,利用操作符 `- > `可以通过结构体指针访问结构体属性
//定义学生结构体
struct Student
{
string name;//姓名
int age;//年龄
int score;//分数
};
int main()
{
//1.创建学生的结构体变量
struct Student s = { "张三",18,100 };
//2.通过指针指向结构体变量
struct Student* p = &s;//struct可以省略
//3.通过指针访问结构体变量中的数据
//通过结构体指针访问结构体中的属性,需要用“->”,即指针通过 -> 操作符可以访问成员
cout << "姓名:" << p->name << " " << "年龄:"
<< p->age << " " << "分数:" << p->score << endl;
system("pause");
return 0;
}


作用: 结构体中的成员可以是另一个结构体
例如:每个老师辅导一个学员,一个老师的结构体中,记录一个学生的结构体
#include
#include // 姓名是string类型
using namespace std;
//定义学生结构体
struct student
{
string name;//姓名
int age;//年龄
int score;//分数
};
//定义老师结构体
struct teacher
{
int id;//教师编号
string name;//教师姓名
int age;//年龄
struct student stu;//辅导的学生
};
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.name << endl;
cout << "辅导学生姓名:" << t.stu.name << " 年龄:" << t.stu.age
<< " 考试分数:" << t.stu.score << endl;
system("pause");
return 0;
}

作用:将结构体作为参数向函数中传递
传递方式有两种:
#include
#include
using namespace std;
//定义学生结构体
struct student
{
string name;//姓名
int age;//年龄
int score;//分数
};
//打印学生信息函数
//1.值传递 (形参改变不改变实参)
void printStudent1(struct student s)
{
s.age = 100;// 形参内部打印年龄为100
cout << "子函数1 姓名:" << s.name << " 年龄:" << s.age
<< " 分数:" << s.score << endl;
}
//2.地址传递 (形参改变可以改变实参)
void printStudent2(struct student* p)//用指针接收地址,指针地址传递用“->”
{
p->age = 80;
cout << "子函数2 姓名:" << p->name << " 年龄:" << p->age
<< " 分数:" << p->score << endl;
}
int main()
{
//结构体做函数参数
//将学生传入到一个参数中,打印学生身上的所有信息
//创建结构体变量
struct student s;
s.name = "张三";
s.age = 20;
s.score = 85;
//值传递,age形参值会改变,但实参值不变
printStudent1(s);
cout << "main函数 姓名:" << s.name << " 年龄:" << s.age
<< " 分数:" << s.score << endl;
cout << endl;
//地址传递,age形参值会改变,实参值也会跟着改变
printStudent2(&s);
cout << "main函数 姓名:" << s.name << " 年龄:" << s.age
<< " 分数:" << s.score << endl;
system("pause");
return 0;
}

作用:用const来防止误操作
#include
#include
using namespace std;
//const使用场景
//学生结构体定义
struct student
{
//成员列表
string name; //姓名
int age; //年龄
int score; //分数
};
//将函数中的形参改为指针,可以减少内存空间,而且不会复制新的副本出来
void printStudent(const student* stu) //加const防止函数体中的误操作
{
//stu->age = 100; //加const修饰防止误操作,防止修改
cout << "姓名:" << stu->name << " 年龄:" << stu->age << " 分数:"
<< stu->score << endl;
}//指针访问用“->”
int main()
{
student stu = { "张三",18,100 };
printStudent(&stu);
system("pause");
return 0;
}

案例描述:
学校正在做毕设项目,每名老师带领5个学生,总共有3名老师,需求如下:
设计学生和老师的结构体,在老师的结构体中,有老师姓名和一个存放5名学生的数组作为成员
学生的成员有姓名、考试分数,创建数组存放3名老师,通过函数给每个老师及所带的学生赋值
最终打印出老师数据以及老师所带的学生数据

这里struct Teacher tArray[ ]可以用struct Teacher* tArray替代,使用的是指针,其他的不变。
#include
#include
#include
using namespace std;
//定义学生结构体
struct Student
{
string sName;//姓名
int score;//分数
};
//定义老师结构体
struct Teacher
{
string tName;//教师姓名
struct Student sArray[5];//学生数组
};
//给老师和学生赋值的函数,使用数组和长度
void allocateSpace(struct Teacher tArray[], int len)
{
//string nameSeed = "ABCDE"; // 老师3个,每个老师指导5个学生
char nameSeed[] = "ABCDE"; // 这种方法也可以
//给老师赋值
for (int i = 0; i < len; i++)
{
tArray[i].tName = "Teacher_";
tArray[i].tName += nameSeed[i];
//通过循环给每名老师所带的学生赋值
for (int j = 0; j < 5; j++)
{
tArray[i].sArray[j].sName = "Student_";
tArray[i].sArray[j].sName += nameSeed[j];
int random = rand() % 61 + 40;//学生分数在40~100(如果61改为60则范围是40~99)
tArray[i].sArray[j].score = random;
}
}
}
//打印所有信息,使用数组和长度
void printInfo(struct Teacher tArray[], int len)
{
for (int i = 0; i < len; i++)
{
cout << "老师姓名:" << tArray[i].tName << endl;
for (int j = 0; j < 5; j++)
{
cout << "\t学生姓名:" << tArray[i].sArray[j].sName << " "
<< " 考试分数:" << tArray[i].sArray[j].score << endl;
}
cout << endl;
}
}
int main()
{
//随机数种子
srand((unsigned int)time(NULL));// 加#include
//1.创建3名老师的数组
struct Teacher tArray[3];
//2.通过函数给3名老师的信息赋值,并给老师带的学生信息赋值
int len = sizeof(tArray) / sizeof(tArray[0]);// 这里 len = 3
allocateSpace(tArray, len);
//3.打印所有老师及所带的学生信息
printInfo(tArray, len);
system("pause");
return 0;
}

案例描述:设计一个英雄的结构体,包括成员姓名,年龄,性别;创建结构体数组,数组中存放5名英雄。
通过冒泡排序的算法,将数组中的英雄按照年龄进行升序排序,最终打印排序后的结果。
五名英雄信息如下:
{"刘备",23,"男"},
{"关羽",22,"男"},
{"张飞",20,"男"},
{"赵云",21,"男"},
{"貂蝉",19,"女"},
#include
#include
using namespace std;
//1.设计英雄结构体
struct Hero
{
string name;//姓名
int age;//年龄
string sex;//性别
};
//冒泡排序——实现年龄升序排列
void bubbleSort(struct Hero heroArray[], int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
//如果j下标的元素年龄大于j+1下标的元素年龄,就交换两个元素
if (heroArray[j].age > heroArray[j + 1].age)
{
struct Hero temp = heroArray[j];//temp是结构体类型
heroArray[j] = heroArray[j + 1];
heroArray[j + 1] = temp;
}
}
}
}
//打印排序后数组中的信息
void printHero(struct Hero heroArray[], int len)
{
for (int i = 0; i < len; i++)
{
cout << "姓名:" << heroArray[i].name << " 年龄:" << heroArray[i].age
<< " 性别:" << heroArray[i].sex << endl;
}
}
int main()
{
//2.创建数组存放5名英雄
struct Hero heroArray[5] =
{
{"刘备",23,"男"},
{"关羽",22,"男"},
{"张飞",20,"男"},
{"赵云",21,"男"},
{"貂蝉",19,"女"},
};
int len = sizeof(heroArray) / sizeof(heroArray[0]);
cout << "排序前打印:" << endl;
for (int i = 0; i < len; i++)
{
cout << "姓名:" << heroArray[i].name << " 年龄:" << heroArray[i].age
<< " 性别:" << heroArray[i].sex << endl;
}
cout << endl;
//3.对数组进行排序,按照年龄进行升序排列
bubbleSort(heroArray, len);
cout << "排序后打印:" << endl;
//4.将排序后的结果打印输出
printHero(heroArray, len);
system("pause");
return 0;
}
