18.指针-指针的进阶使用
18.1 知识点
指针变量所占内存空间
不管何种变量类型的指针变量,所占的内存空间都是一样的,因为它是用来存储变量的内存地址的(存储内存单元的门牌号码)。门牌号码是有范围限制的,不需要因为变量类型的不同而改变大小。
在不同位数的操作系统和不同编译器设置上,指针所占的字节数有所不同:
- 32位:4字节
- 64位:8字节(常见)
int a = 1;
int* p = &a;
cout << sizeof(p) << endl; // 8
char c = 'A';
char* p_c = &c;
cout << sizeof(p_c) << endl; // 8
bool b = true;
bool* p_b = &b;
cout << sizeof(p_b) << endl; // 8
&(地址符号) 和 *(解引用操作符) 的混合使用
回顾
int d = 1;
// & 地址符号 主要用于获取变量地址,用于指针赋值
int* p2 = &d;
cout << p2 << endl; // 0000007E06B2F504
// * 解引用操作符 主要用于获取地址中存储的内容
cout << *p2 << endl; // 1
// 获取指针变量的地址
cout << &p2 << endl; // 0000007E06B2F528
&* 和 *& 混合使用
& 使用*
使用时从右向左开始结合,表示先获取指针指向地址的值,再获取该值的地址,相当于获取指针指向的内存地址。
int* pp = &*p2; // *p2得到d,&d得到d的地址,赋值给pp cout << p2 << endl; // 0000007E06B2F504 cout << pp << endl; // 0000007E06B2F504 cout << &p2 << endl; // 0000007E06B2F528 cout << &pp << endl; // 0000007E06B2F548
***& 使用**
使用时从右向左开始结合,表示先获取变量的地址,再获取该地址中存储的值,相当于是获取一个变量的值。
cout << *&d << endl; // 1 // &d得到d的地址,*d的地址得到指向该地址的值,即d的值
*& 是可以和指针变量配合使用的。相当于先得到指针自己的地址,然后再通过这个地址得到其中存储的内容——指针存储的地址值。
cout << &d << endl; // 0000007E06B2F504 d的地址 cout << *&p2 << endl; // 0000007E06B2F504 p2存着d的地址,&p2是p2的地址,*p2的地址得到的是p2存着的地址,即d的地址 cout << p2 << endl; // 0000007E06B2F504 p2存着d的地址
注意
只要记住了 *
和 &
两个符号的作用,那么在处理混合使用时,就可以分开来看,从右往左看即可。
*
获取地址中存储的变量的值&
获取变量的地址
指针的自增减运算
指针是可以做自增减运算的。由于指针存储的是变量的地址,当我们做指针自增减运算时,相当于是对地址进行运算,并且地址的变化是遵循以下规律的:
- 自增:将指针向前移动一个元素的大小
- 自减:将指针向后移动一个元素的大小
元素大小:指针变量的类型决定,sizeof(指针变量类型)
得到的就是元素大小。
举例说明
int
是 4 字节,每次自增都会让地址跳跃 4 字节。
int bb = 10;
int* ptrbb = &bb;
cout << ptrbb << endl; // 000000EEE90FF7D4
ptrbb++;
cout << ptrbb << endl; // 000000EEE90FF7D8
++ptrbb;
cout << ptrbb << endl; // 000000EEE90FF7DC
ptrbb = ptrbb + 1;
cout << ptrbb << endl; // 000000EEE90FF7E0
ptrbb = ptrbb - 3;
cout << ptrbb << endl; // 000000EEE90FF7D4
空类型指针
空类型指针是一种特殊的指针,它表示不特定类型的指针。指针变量可以指向任意的变量类型,具体存放何种类型由后续赋值决定。赋值后,如果需要使用需要强转为对应的数据类型。
void* pVoid;
short s = 55;
pVoid = &s;
cout << pVoid << endl; // 00000044C7CFFA74
short s2 = *(short*)pVoid;
cout << s2 << endl; // 55
18.2 知识点代码
Lesson18_指针_指针的进阶使用.cpp
#include <iostream>
using namespace std;
int main()
{
std::cout << "指针的进阶使用\n";
#pragma region 知识点一 指针变量所占内存空间
//不管何种变量类型的指针变量
//所占的内存空间都是一样的
//因为它是用来存储变量的内存地址的(存储内存单元的门牌号码)
//门牌号码是有范围限制的
//不需要因为变量类型的不同而改变大小
//在不同位数的操作系统 和 不同编译器设置上
//指针所占的字节数有所不同
//32位:4字节
//64位:8字节(常见)
int a = 1;
int* p = &a;
cout << sizeof(p) << endl;//8
char c = 'A';
char* p_c = &c;
cout << sizeof(p_c) << endl;//8
bool b = true;
bool* p_b = &b;
cout << sizeof(p_b) << endl;//8
#pragma endregion
#pragma region 知识点二 &(地址符号) 和 *(解引用操作符) 的混合使用
//回顾
int d = 1;
//& 地址符号 主要用于获取变量地址 用于指针赋值
int* p2 = &d;
cout << p2 << endl;//0000007E06B2F504
//* 解引用操作符 主要用于获取地址中存储的内容
cout << *p2 << endl;//1
// 获取指针变量的地址
cout << &p2 << endl;//0000007E06B2F528
//& * 这两个符号是可以混合使用的
//主要用法有两种
//1.&*
// 使用时从右向左开始结合
// 表示先获取指针指向地址的值,再获取该值的地址
// 相当于获取指针指向的内存地址
int* pp = &*p2;//*p2得到d &d得到d的地址 赋值给pp
//两个指针指向的地址是一样的 都是指向的
cout << p2 << endl;//0000007E06B2F504
cout << pp << endl;//0000007E06B2F504
//两个指针变量指向的地址是不一样的 在两块内存空间
cout << &p2 << endl;//0000007E06B2F528
cout << &pp << endl;//0000007E06B2F548
//&* 只能和指针变量配合使用
//&*d;//报错 &*只能用于指针变量
//2.*&
// 使用时从右向左开始结合
// 表示先获取变量的地址,再获取该地址中存储的值
// 相当于是获取一个变量的值
cout << *&d << endl;//1 &d得到d的地址 *d的地址 得到指向该地址的值 该地址指向d 即d的值
//*&是可以和指针变量配合使用的
//相当于先得到指针自己的地址,然后再通过这个地址得到其中存储的内容
//指针存储的地址值
cout << &d << endl;//0000007E06B2F504 d的地址
cout << *&p2 << endl;//0000007E06B2F504 p2存着d的地址 &p2是p2的地址 *p2的地址 得到的是p2存着的地址 即d的地址
cout << p2 << endl;//0000007E06B2F504 p2存着d的地址
//注意:
//只要记住了*和&两个符号的作用
//那么在处理混合使用时,就分开看就可以了,从右往左看即可
//*获取地址中存储的变量的值
//&获取变量的地址的
#pragma endregion
cout << "***************" << endl;
#pragma region 知识点三 指针的自增减运算
//指针是可以做自增减运算的
//由于指针存储的是变量的地址
//当我们做指针自增减运算时
//相当于是对地址进行运算
//并且地址的变化是遵循以下规律的
// 自增:将指针向前移动 一个元素的大小
// 自减:将指针向后移动 一个元素的大小
// 元素大小:指针变量的类型决定,sizeof(指针变量类型)得到的就是元素大小
//
// 举例说明:int是4字节 以下每次自增都是让地址跳跃4字节
int bb = 10;
int* ptrbb = &bb;
cout << ptrbb << endl;//000000EEE90FF7D4
ptrbb++;
cout << ptrbb << endl;//000000EEE90FF7D8
++ptrbb;
cout << ptrbb << endl;//000000EEE90FF7DC
ptrbb = ptrbb + 1;
cout << ptrbb << endl;//000000EEE90FF7E0
ptrbb = ptrbb - 3;
cout << ptrbb << endl;//000000EEE90FF7D4
#pragma endregion
cout << "***************" << endl;
#pragma region 知识点四 空类型指针
//空类型指针是一种特殊的指针
//它表示不特定类型的指针
//指针变量可以指向任意的变量类型
//具体存放何种类型,由后续赋值决定
//赋值后,如果需要使用需要强转为对应的数据类型
void* pVoid;
short s = 55;
pVoid = &s;
cout << pVoid << endl;//00000044C7CFFA74
short s2 = *(short*)pVoid;
cout << s2 << endl;//55
#pragma endregion
}
18.3 练习题
指针占用多少内存空间?
int i = 10;
int* p = &i;
cout << sizeof(p) << endl; // 8 在64位操作系统,32位是4
指针自增减的规则是什么?
p++ ++p p– –p p += 3 p -= 2 p = p + n
会按照元素所占内存空间来进行门牌地址的偏移,例如整型每加一次加4个字节
请说明以下代码中打印结果的含义
注意:不要通过敲代码验证,直接回答
int a = 10;
int* p = &a;
cout << *&p << endl;
int a = 10;
int* p = &a;
cout << *&p << endl; // a的地址
cout << p << endl; // a的地址
cout << &a << endl; // a的地址
请说明以下代码中可能存在的问题
注意:不要通过敲代码验证,直接回答
int a = 70000;
int* p = &a;
cout << *(short*)p << endl;
代码中先将 int 类型的指针 p 强制转换为 short* 类型的指针,然后进行解引用操作。
int 类型通常占用 4 个字节(具体取决于编译器和系统,但一般为 4 字节),而 short 类型通常占用 2 个字节。
当 int 类型的变量 a 的值为 70000 时,其在内存中的二进制表示是特定的,将 int* 指针转换为 short* 指针并解引用,会导致只取到 a 的低 2 字节数据。
对于 70000,其十六进制表示为 0x11170,将其存储在内存中,低 2 字节的数据为 0x170,转换为十进制就是 4464。
这种强制类型转换会造成数据截断,丢失了 a 的高 2 字节信息,可能导致结果不符合预期。
int a = 70000;
int* p = &a;
cout << *(short*)p << endl; // 4464
18.4 练习题代码
Lesson18_练习题.cpp
#include <iostream>
using namespace std;
int main()
{
std::cout << "指针的更多使用 练习题\n";
#pragma region 练习题一
//指针占用多少内存空间?
//int i = 10;
//int* p = &i;
//cout << sizeof(p) << endl;//8 在64位操作系统 32位是4
#pragma endregion
#pragma region 练习题二
//指针自增减的规则是什么?
//p++ ++p p-- --p p += 3 p -= 2 p = p + n
//会按照元素所占内存空间来进行门牌地址的偏移 例如整形每加一次加4个字节
#pragma endregion
#pragma region 练习题三
/*请说明以下代码中打印结果的含义
注意:不要通过敲代码验证,直接回答
int a = 10;
int* p = &a;
cout << *&p << endl;*/
//int a = 10;
//int* p = &a;
//cout << *&p << endl;//a的地址
//cout << p << endl;//a的地址
//cout << &a << endl;//a的地址
#pragma endregion
#pragma region 练习题四
/*请说明以下代码中可能存在的问题
注意:不要通过敲代码验证,直接回答
int a = 70000;
int* p = &a;
cout << *(short*)p << endl;*/
int a = 70000;
int* p = &a;
cout << *(short*)p << endl;//4464
//代码中先将 int 类型的指针 p 强制转换为 short* 类型的指针,然后进行解引用操作。
//int 类型通常占用 4 个字节(具体取决于编译器和系统,但一般为 4 字节),而 short 类型通常占用 2 个字节。
//当 int 类型的变量 a 的值为 70000 时,其在内存中的二进制表示是特定的,将 int* 指针转换为 short* 指针并解引用,会导致只取到 a 的低 2 字节数据。
//对于 70000,其十六进制表示为 0x11170,将其存储在内存中,低 2 字节的数据为 0x170,转换为十进制就是 4464。
//这种强制类型转换会造成数据截断,丢失了 a 的高 2 字节信息,可能导致结果不符合预期。
#pragma endregion
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com