指针
一、指针基本概念
作用:可以通过指针间接访问内存,通过指针保存一个地址
-
内存编号是从0开始记录的,一般采用十六进制数字表示
-
可以利用指针变量保存地址
二、指针变量的定义和使用
//1、定义指针
int a = 10;
// 基本语法:数据类型 * 指针变量名;
int * p;
// 让指针记录变量a的地址
p = &a;
cout << "a 的地址 为:" << &a << endl;
cout << "a 的地址 为:" << p << endl; // 输出就是 a 的地址
//2、操作指针
/*
通过解引用的方式找到指针指向的内存,指针前加 * 代表解引用
找到指针指向内存中的数据
*/
*p = 1000; //通过指针找到a的地址,修改a的值
cout << "a = " << a << endl;
cout << "*p = " << *p << endl;
/*
a = 1000
*p = 1000
*/
三、指针所占的内存空间
//指针所占的内存空间
//在64位OS系统下,指针占8个字节大小,不管什么数据类型
//在32位OS系统下,指针占用4个字节大小
cout << "sizeof (int *) =" << sizeof(p) <<endl; //8
cout << "sizeof (int *) =" << sizeof(int *) <<endl; //8
cout << "sizeof (int *) =" << sizeof(float *) <<endl; //8
cout << "sizeof (int *) =" << sizeof(char *) <<endl; //8
cout << "sizeof (int *) =" << sizeof(double *) <<endl; //8
四、空指针和野指针
空指针:指针变量指向内存空间为0的空间
用途:初始化指针变量
attention:空指针指向的内存是不可以访问的
// 空指针,用于对指针变量进行初始化
int *p = NULL;
// 空指针 是不可以进行访问的,0~255之间的内存编号是系统占用,因此不可以访问
*p = 100; // 运行就报错,空指针不可以访问
野指针:指向变量指向非法的内存空间
//野指针
// int *a = (int *)Ox1100;
// cout << *p << endl;
attention:空指针和野指针都不是我们申请的内存空间,不能访问
五、const修饰指针
1、const 修饰指针 : 常量指针
2、const 修饰常量 : 指针常量
3、const 不仅修饰指针,还修饰常量
int b = 10;
int c = 10;
// const 修饰指针
//1、const 修饰指针, 常量指针,不可以修改值,指针的指向可以改
const int *m = &b;
//*p = 20; 错误
m = &c; // 正确
cout << *m << endl;
//2、const 修饰常量,指针常量,不可以修改指向,值可以修改
int * const n = &b;
//n = &c; //错误
*n =5;
cout << *n << endl;
//3、const 修饰指针和常量,值和指向都不可以修改
const int * const r = &b;
// *r = 10; 错
// r = &c; 错
六、指针和数组
作用:利用指针访问数组中的元素
//指针和数组
int arr[] = {165,2,334,40,55};
for (int i = 0;i < 5;i++){
cout << "第" << i+1 <<"个数为:" << arr[i] << endl;
}
int *ar = arr;
cout << arr << endl; //输出的是数组的首地址
cout << *ar << endl; // 输出第一个数165
ar++; //让指针向后偏移4个字节
cout << *ar << endl; // 输出第二个数2
ar--;
cout << "-------" <<endl;
for(int i = 0 ;i < 5 ; i++){
cout << *ar << endl;
ar++;
}
七、指针和函数
作用:利用指针作为函数参数,可以修改实参的值
//指针和函数
//1、值传递
int m1 = 10;
int n1 = 5;
swap1(m1,n1);
cout << "m1 = " << m1 << endl;
cout << "n1 = " << n1 << endl;
cout << "-------" <<endl;
//2、地址传递 ,改变实参的值
swap2( &m1 , &n1 );
cout << "m1 = " << m1 << endl;
cout << "n1 = " << n1 << endl;
void swap1(int a ,int b){
int temp = a;
a = b;
b = temp;
cout << " swap1 m1 = " << a << endl;
cout << " swap1 n1 = " << b << endl;
}
void swap2(int *a ,int *b){
int temp = *a;
*a = *b;
*b = temp;
cout << " swap2 m1 = " << *a << endl;
cout << " swap2 n1 = " << *b << endl;
}
八、指针、数组、函数
案例:封装一个函数,使用冒泡排序,实现对整型数组的升序排列
int arr1[] = {345,56,21,54,3,34,11};
maopao(arr1);
for (int i = 0;i <7 ;i++){
cout << arr1[i] <<endl;
}
void swap2(int *a ,int *b){
int temp = *a;
*a = *b;
*b = temp;
}
void maopao(int *arr){ //传进来时数组名,就是地址,可以用*arr接受,也可以用 arr[]
for (int i = 0; i < 7;i++){
for (int j = 0 ; j < 7-i ;j++){
if (arr[j] > arr[j+1] && j < 6){
swap2(&arr[j],&arr[j+1]);
}
}
}
}
结构体
一、基本概念
结构体属于用户自定义的数据类型,允许用户储存不同的数据类型
二、结构体定义及使用
语法:struct 结构体名 { 结构体成员列表};
1、struct 结构体名 变量名
2、struct 结构体名 变量名 = { 成员1 值,成员2 值}
3、定义结构体时顺便创建变量
// 1、创建学生的数据类型
struct Student{
// 成员变量,自定义的数据类型
string Sname;
int Sage;
int Score;
}s3; // 顺便创建结构体变量
int main(){
// 2、通过学生数据类型创建具体学生,三种创建方式
//第一种,struct 关键字可以省略
struct Student s1;
//进行赋值
s1.Sname = "fangxn";
s1.Sage = 14;
s1.Score = 99;
cout << "name:" << s1.Sname << endl;
cout << "age:" << s1.Sage << endl;
cout << "score:" << s1.Score << endl;
//第二种
struct Student s2 = {"daihan",24,99};
cout << s2.Sname << s2.Sage << s2.Score << endl;
//第三种,在定义结构体时顺便创建结构体变量
s3.Sname = "haha";
s3.Sage = 24;
s3.Score = 60;
cout << s3.Sname << s3.Sage << s3.Score << endl;
return 0;
}
三、结构体数组
将自定义的结构体放到数组中方便维护
语法:struct 结构体名 数组名【元素个数】= { {}, {} , {}}
// 结构体数组
// 定义结构体,写在函数外
struct stu{
string name;
int age;
int score;
};
// 创建结构体数组
struct stu stuarry[3] = {
{"张三",18,90},
{"李四",20,91},
{"哈哈",24,95}
};
// 给结构体数组中的元素赋值
stuarry[0].name = "娜娜";
stuarry[0].age = 20;
stuarry[0].score = 60;
// 遍历结构体数组
for(int i = 0;i < 3; i++){
cout << stuarry[i].name << "\t" ;
cout << stuarry[i].age << "\t" ;
cout << stuarry[i].score << endl;
}
四、结构体指针
作用:通过指针访问结构体中的变量
// 结构体指针
// 创建学生结构体变量
struct Student d1 = {"小",22,100};
// 通过指针指向结构体变量
struct Student *p = &d1;
// 通过指针访问结构体变量中的数据
cout << p->Sname << endl;
cout << p->Sage << endl;
cout << p->Score << endl;
五、结构体嵌套结构体
作用:结构体中的成员可以是另一个结构体
例如:每个老师辅导一个学生,老师的结构中包含学生的结构体
struct teacher{
string name;
int id;
int age;
struct Student stt; // 辅导的学生
};
//结构体的嵌套
//创建老师
struct teacher tt = {"吴胜",001,33,{"小戴",22,100}};
cout << tt.stt.Sname << tt.stt.Sage << tt.stt.Score << endl;
六、结构体做函数参数
作用:将结构体作为参数向函数中传递
方式:值传递,地址传递
// 值传递
void printData(struct Student d){
cout << "子函数中输出:" << d.Sname << "\t" << d.Sage << "\t" << d.Score <<endl;
};
// 地址传递
void printData1(struct Student *p){
p->Sname = "我现在没有名字";
};
// 结构体作为函数参数
// 将学生传入一个参数中,打印学生上的所有信息
struct Student d2 = {"小戴",22,100};
printData(d2);
printData1(&d2);
cout << d2.Sname << endl;
七、结构体中const使用场景
作用:用 condst 来防止误操作
void printData1(const struct Student *p){
//p->Sname = "我现在没有名字"; 只能去地址,不能修改其中的值
};