17.指针-指针的基础使用
17.1 知识点
指针的声明
声明写法:
变量类型* 指针变量名;
或者:
变量类型 *指针变量名;
注意事项:
- 任何变量类型都可以声明为指针变量类型,只需要在变量类型后面加上一个
*
。 - 指针变量的常用命名规范:
- 前缀法:使用
p
或ptr
作为前缀。 - 后缀法:使用
_p
或_ptr
作为后缀。 - 指针类型变量名:
ptr\p+变量类型+变量名
,例如ptrIntValue
、pIntValue
。
- 前缀法:使用
示例:
int* p_i;
char* ptr_c;
float* f_ptr;
unsigned* u_p;
string* str_ptr;
int* ptrIntValue;
指针的初始化
指针必须赋值为内存中的有效地址(已经分配给变量的地址)。也就是说,在使用指针变量时,必须让它指向一个已经声明的变量,并且该变量的类型需要和指针变量的类型一致。
示例:
int i = 10;
// 如果我们想声明一个指针指向i的内存地址,我们需要获取到i的地址
// 我们可以利用地址符号 &i 来获取
int* p_i2 = &i;
cout << p_i2 << endl; // 0000007AE415F734
int* p_i3;
p_i3 = &i;
cout << p_i3 << endl; // 0000007AE415F734
为什么要用相同的变量类型的指针去存储地址?
- 主要是因为一个变量所占用的内存单元可能是多个,而指针变量存储的是它第一个内存单元的门牌号。如果指针变量类型和存储的变量类型不一致,那么之后就无法准确地读取对应的内存单元,从而获取其中的内容。
示例:
float f = 5.5f;
float* f_ptr2 = &f;
cout << f_ptr2 << endl; // 0000007AE415F794
指针的解引用操作符
所谓的指针解引用操作符其实就是 *
。如果我们想要获取指针所指向的内存地址中存储的值,只需要在指针变量前加上解引用操作符,就可以得到其中存储的值。
示例:
cout << *p_i2 << endl; // 10
cout << *f_ptr2 << endl; // 5.5
我们还可以利用解引用操作符改变原有的值:
*p_i2 = 99;
cout << *p_i2 << endl; // 99
cout << i << endl; // 99
空指针和野指针
- 空指针:不指向任何有效内存的指针。可以将指针赋值为
nullptr
或NULL
(老版本)表示该指针为空指针。
示例:
int* ptr_i5; // = nullptr;
ptr_i5 = nullptr;
- 野指针:指向无效或不可预知内存地址的指针。野指针会导致程序出现各种不可预料的错误,例如程序崩溃、数据损坏、访问非法内存等。
野指针的主要出现原因:
- 未初始化的指针(目前主要遇到的为该种情况)。
- 指向内存被释放后仍使用的指针。
- 指向内存位置超出作用域的指针。
- 指向未定义为分配的内存的指针。
为了避免出现问题:
- 在声明指针时,如果不马上使用,建议将指针声明为空指针。
总结
- 指针是存储变量内存地址的变量。
- 想要获取某个变量的地址,使用地址符号
&
来获取。 - 想要获取指针指向的内存地址中存储的值,使用解引用操作符(取值操作符)
*
。 - 在声明指针时,如果不马上使用该指针,建议将其声明为空指针
nullptr
。 - 野指针会对程序带来不可预估的问题,需要引起重视。
对于 *
和 &
的记忆口诀:
- 看见
&
想地址。取地址。 - 看见
*
想内容。解引用,取地址中的值。
17.2 知识点代码
Lesson17_指针_指针的基础使用.cpp
#include <iostream>
using namespace std;
int main()
{
std::cout << "指针的基础使用\n";
#pragma region 知识点一 指针的声明
//声明写法:
//变量类型* 指针变量名;
//或
//变量类型 *指针变量名;
//注意:
//1.任何变量类型都可以声明为指针变量类型
// 就是在变量类型后面加一个*
//2.指针变量的常用命名规范
// 前缀法:p或ptr作为前缀
// 后缀法:_p或_ptr作为后缀
// 指针类型变量名:ptr\p+变量类型+变量名 => ptrIntValue、pIntValue
// 等等
int* p_i;
char* ptr_c;
float* f_ptr;
unsigned* u_p;
string* str_ptr;
int* ptrIntValue;
#pragma endregion
#pragma region 知识点二 指针的初始化
//指针必须赋值为内存中的有效地址(已经分配给变量的地址)
//也就是说,根据我们目前学习的知识,我们在使用指针变量时
//必须让他指向一个已经声明了的变量,并且该变量的类型需要和指针变量的变量类型一致
int i = 10;
//如果我们想声明一个指针指向i的内存地址,我们需要获取到i的地址
//我们可以利用 地址符号 &i 来获取
int* p_i2 = &i;
cout << p_i2 << endl;//0000007AE415F734
int* p_i3;
p_i3 = &i;
cout << p_i3 << endl;//0000007AE415F734
//为什么要用相同的变量类型的指针去存储地址
//主要是因为 一个变量它所占用的内存单元可能是多个 而指针变量存储的是它第一个内存单元的门牌号
//如果指针变量类型和存储的变量类型不一致,那么之后就无法准确的读取对应个数个内存单元
//来获取其中的内容
float f = 5.5f;
float* f_ptr2 = &f;
cout << f_ptr2 << endl;//0000007AE415F794
#pragma endregion
#pragma region 知识点三 指针的解引用操作符
//所谓的 指针解引用操作符 其实就是 *
//如果我们想要获取到指针所指向的内存地址中存储的值
//我们只需要在指针变量前加一个解引用操作符,便可以得到其中存储的值
cout << *p_i2 << endl;//10
cout << *f_ptr2 << endl;//5.5
//并且我们还可以利用它改变原有的值
*p_i2 = 99;
cout << *p_i2 << endl;//99
cout << i << endl;//99
#pragma endregion
#pragma region 知识点四 空指针和野指针
//空指针是
//不指向任何有效内存的指针
//给指针赋值为 nullptr 或 NULL(老版本) 表示该指针为空指针
int* ptr_i5;// = nullptr;
ptr_i5 = nullptr;
//野指针是
//指向无效或不可预知内存地址的指针
//野指针会导致程序出现各种不可预料的错误
//比如:程序崩溃、数据损坏、访问非法内存等等
//主要出现的原因:
//1.未初始化的指针(目前主要遇到的为该种情况)
//2.指向内存被释放后仍使用的指针
//3.指向内存位置超出作用域的指针
//4.指向未定义为分配的内存的指针
//等等
//注意:
//为了避免出问题
//在声明指针时如果不马上使用
//建议将指针声明为空指针
#pragma endregion
#pragma region 总结
//1.指针就是存储变量内存地址的变量
//2.想要获取某一个变量地址 使用 地址符号 &来获取
//3.想要获取指针指向内存地址中存储的值 使用解引用操作符(取值操作符)*
//4.在声明指针时,如果不马上使用该指针,建议大家将其声明为空指针 nullptr
//5.野指针会对程序带来不可预估的问题,需要引起重视
//对于*和&的记忆口诀
//看见&想地址
//看见*想内容
#pragma endregion
}
17.3 练习题
请问以下代码是否正确,为什么?
int *p;
int a = 100;
p = 100;
不正确。指针应该指向地址而不是具体的值。
请问以下代码的打印结果是多少?
int a1 = 10;
int* p1 = &a1;
int a2 = *p1;
a2 = 20;
cout << *p1 << endl;
cout << a1 << endl;
都是10。a2
只是把值复制过来,不会影响到 a1
和 p1
,a2
是自己新开的房间。
请问以下代码的打印结果的含义是什么?
int a = 10;
int* p = &a;
cout << p << endl;
cout << &p << endl;
cout << *p << endl;
- 整型变量
a
的地址(在p
中存储) - 指针型变量
p
的地址(指向指针变量的地址) - 整型变量
a
的值(10)
请利用指针知识比较两个数的大小
提示:指针 P1
和 P2
,P1
始终要存储更大的值,P2
始终要存储最小的值。最后打印信息时利用指针变量打印结果。
int a = 10;
int b = 20;
int* p1 = &a; // -> 10
int* p2 = &b; // -> 20
// 检查交换
if (*p1 < *p2)
{
int* p = p1;
p1 = p2;
p2 = p;
}
cout << *p1 << endl; // 20
cout << *p2 << endl; // 10
17.4 练习题代码
Lesson17_练习题.cpp
#include <iostream>
using namespace std;
int main()
{
std::cout << "指针的基础使用 练习题\n";
#pragma region 练习题一
/*请问以下代码是否正确,为什么?
注意:不要通过敲代码验证,直接回答
int* p;
int a = 100;
p = 100;*/
//不正确 指针应该指向地址而不是具体的值
#pragma endregion
#pragma region 练习题二
/*请问以下代码的打印结果是多少
注意:不要通过敲代码验证,直接回答
int a1 = 10;
int* p1 = &a1;
int a2 = *p1;
a2 = 20;
cout << *p1 << endl;
cout << a1 << endl;*/
//都是10 a2只是把值复制过来 不会影响到a1和p1 a2是自己新开的房间
#pragma endregion
#pragma region 练习题三
/*请问以下代码的打印结果的含义是什么?
注意:不要通过敲代码验证,直接回答
int a = 10;
int* p = &a;
cout << p << endl;
cout << &p << endl;
cout << *p << endl;*/
//整型变量a的地址(在p中存储)
//指针型变量p的地址(指向指针变量的地址)
//整型变量a的值(10)
#pragma endregion
#pragma region 练习题四
/*请利用指针知识比较两个数的大小
提示:指针P1和P2,P1始终要存储更大的值,P2始终要存储最小的值
最后打印信息时利用指针变量打印结果*/
int a = 10;
int b = 20;
int* p1 = &a;// ->10
int* p2 = &b;// ->20
//检查交换
if (*p1 < *p2)
{
int* p = p1;
p1 = p2;
p2 = p;
}
cout << *p1 << endl; // 20
cout << *p2 << endl; // 10
#pragma endregion
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com