21.指针:通过指针间接访问内存
(1)指针的基本概念
1)内存编号从0开始记录,一般用十六进制数字表示;
2)利用指针变量保存地址
(2)指针变量的定义和使用
1)指针变量定义语法: 数据类型 *变量名;
2)&:取址符号 int a = 10; int * p; p=&a;(int *p = &a;)
*:解引用符号 a = *p;
(3)指针所占用的内存空间:指针也是一种数据类型
1)指针所占内存空间 sizeof(int *);sizeof(double *);
2)在32位操作系统下,不管什么数据类型,指针都占4个字节的空间大小
在64位操作系统下,不管什么数据类型,指针都占8个字节的空间大小
(4)空指针和野指针
1)空指针:指针变量指向内存中编号为0的空间(NULL)
用途:初始化指针变量
空指针指向的内存不可以被访问
0~255之间的内存编号是系统占用的,故而不可以访问
2)野指针:指针变量指向非法的内存空间
(5)const修饰指针
1)const修饰指针:常量指针
Const int *p =&a;
指针指向可以修改,但是指针指向的值不可以更改
2)const修饰常量:指针常量
Int * const p = &a;
指针指向不可以更改,但是指针指向的值可以更改
3)const既修饰指针,又修饰常量
Const int * const p =&a;
都不可以更改
(6)指针和数组:利用指针访问数组中的元素
1)int arr[10]; 使用
Int p arr; //指向第一个元素,使用p即可访问
P++; //指向下一个元素的地址
(7)指针与函数:利用指针做函数参数,可以修改实参的值(地址传递)
不需要修改实参,就用值传递
需要修改实参,使用地址传递
(8)指针、数组和函数:封装一个函数,利用冒泡排序,实现对整形数组的升序排序
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;
}
}
}
}
22.结构体:用户自定义的数据类型,允许用户存储不同的数据类型
(1)结构体的定义和使用
1)语法:struct 结构体名{结构体成员列表};(结构体定义)
2)通过结构体创建变量的方式(结构体变量)
Struct 结构体名 变量名;
Struct 结构体名 变量名 = {成员1值,成员2值…};
定义结构体时顺便创建变量;
(2)结构体数组:将自定义的结构体放入到数组中方便维护
1)语法:struct 结构体名 数组名[元素个数] = {{ },{ },…,{ }};//下标默认从零开始赋值
(3)结构体指针:通过指针访问结构体中的成员
1)利用操作符“->”,可以通过结构体指针访问结构体属性
2)三步:创建结构体变量: struct student s = { };
通过指针指向结构体变量:struct student *p = &s;
通过指针访问结构体变量中的数据:p->name; p->age;p->score;
(4)结构体嵌套结构体:结构体中的成员可以是另一个结构体(如老师和学生)
1)定义结构体:先定义学生,再定义老师(定义老师时需要学生的结构体来定义)
Struct student {
string name;
Int age;
Int score;};
Struct teacher{
String name;
Int age;
Int id;
Struct student stu;
};
2)使用方法
Struct teacher t = { };
t.stu.name;
t.stu.age;
t.stu.score;
(5)结构体做函数参数:将结构体作为参数向函数中传递
1)值传递:不想改变主函数中的数据
Struct student s; //传递数据
2)地址传递:想改变主函数中的数据
Struct student *p; //传递地址
(6)结构体中const:用const来防止误操作
结构体的地址传递时,在外部函数中可以修改实参值,所以如果不想修改实参值,则使用const来防止误操作: void printstruct(const struct student *p);