这是对C++指针偏移介绍比较好的博文,但是比较分散,我把其进行了整理,原博文地址请见最后,讲的很详细。
C++57个入门知识点_番外1_C++指针偏移在类中的应用及指针偏移原理
- 1. C++指针偏移原理
- 2. C++显示十进制内存地址(不用理解,直接使用)
- 3. C++指针偏移在类中的应用
1. C++指针偏移原理
在C++中我们可以通过指针方便的访问各种类型数据,但我们都知道指针只是一个头地址,而我们需要遍历的数据通常占有大量的空间,那么指针是如何遍历其中的数据呢?这就涉及到指针偏移的一个问题,下面我们看个例子:
这里使用了十进制显示地址函数ip2decimal(),详情见下面的“C++显示十进制内存地址”。
int a[4]={1,2,3,4};
int* p=&a[0];//将数组a的初始地址传给指针p
cout<<"指针p的地址:"<<ip2decimal(p)<<endl;
cout<<"a的地址分别为:"<<endl;
for (int i = 0; i < 4; i++)
{
cout<<ip2decimal(&a[i])<<endl;
}
for (int i = 1; i < 5; i++)
{
cout<<"p地址为:"<<ip2decimal(p)<<"\t数值为:"<<*p<<endl;
p=p+1; //指针增加一个int的偏移量
}
结果为:
通过上述结果我们可以发现,对于一个存储多个数据的int数组,我们可以通过设定个int* p的指针,只需将数组头指针赋给指针p,便可以通过指针p每次增加一个int数据的偏移量准确获取每个int类型数据。这里int数据的偏移量为4,若为其它类型数据则只需偏移该类型的内存大小即可。
我们可以得出结论对于一个指针其遍历数据时,是通过数据与头地址的偏移量来获取的,而不是变量名。
2. C++显示十进制内存地址(不用理解,直接使用)
我们在C++中显示变量地址均为十六进制的,不具有直观性,尤其在分析连续存储的变量内存地址时。下面分享一个可将十六进制地址转为十进制地址显示的代码,需要注意的是,需要在文件头包含stream与string。
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int ip2decimal(void* ip)
{
stringstream str;
string ip_str;
str<<ip;
str>>ip_str;
int bit=0;
int ans=0;
for(int i=ip_str.size();i>=0;--i)
{
if(ip_str[i]>='0'&&ip_str[i]<='9')
{
ans+=(ip_str[i]-'0')*pow(16,bit++);
}else if(ip_str[i]>='A'&&ip_str[i]<='F')
{
ans+=(ip_str[i]-'A'+10)*pow(16,bit++);
}
}
return ans;
}
演示:
int main()
{
int a=100;
cout<<"a的十六进制地址:"<<&a<<endl;
cout<<"a的十进制地址:"<<ip2decimal(&a)<<"\n"<<endl;
double b=12.5;
cout<<"b的十六进制地址:"<<&b<<endl;
cout<<"b的十进制地址:"<<ip2decimal(&b)<<"\n"<<endl;
string str="xiaoming";
cout<<"str的十六进制地址:"<<&str<<endl;
cout<<"str的十进制地址:"<<ip2decimal(&str)<<"\n"<<endl;
int matrix[3]={1,2,3};
cout<<"matrix[0]的十六进制地址:"<<&matrix[0]<<endl;
cout<<"matrix[0]的十进制地址:"<<ip2decimal(&matrix[0])<<endl;
cout<<"matrix[1]的十六进制地址:"<<&matrix[1]<<endl;
cout<<"matrix[1]的十进制地址:"<<ip2decimal(&matrix[1])<<endl;
cout<<"matrix[2]的十六进制地址:"<<&matrix[2]<<endl;
cout<<"matrix[2]的十进制地址:"<<ip2decimal(&matrix[2])<<endl;
system("pause");
return 0;
}
结果:
3. C++指针偏移在类中的应用
我们知道通过指针访问数据时,并不是依据变量名,而是依据变量内存地址与指针的偏移量大小,具体介绍见上面的“C++指针偏移原理”。
现在我们看一个例子,有两个类people与animal:
class people
{
public:
int age_p;
double weight_p;
double height_p;
};
class animal
{
public:
int age_a;
double weight_a;
};
people* p1=new people;
animal* a1;
p1->age_p=24;
p1->weight_p=140;
p1->height_p=180;
通过类的定义我们可以发现,两个类的前两个数据均为int与double,即people与animal这两个类前两项成员变量与对象指针p1、a1的地址偏移量是相同的。既然指针访问数据是根据偏移量大小而不是变量名,那么我们可不可以将p1的地址赋值给a1,然后通过a1去访问age_p与weight_p中的数据呢?
不多说直接上代码:
a1=(animal*)p1; //将people的对象指针p1强转成animal*并赋值给a1
cout<<"指针a1地址:"<<ip2decimal(a1)<<endl;
cout<<"p1->age_p:"<<a1->age_a<<endl;
cout<<"p1->weight_p:"<<a1->weight_a<<endl;
结果为:
完全可行,由此可见对于对象指针访问类中成员变量,同样也是根据成员变量与对象指针的偏移量大小,而不是成员变量名。
参考博文:C++指针偏移在类中的应用;C++指针偏移原理;C++显示十进制内存地址(无需理解,拷贝即用)