指针
指针的定义及使用格式:
int num=0;
int *p = #
该段代码定义了一个指针p,并把它指向num的地址,实现原理是把num变量的地址作为p的值存放在p中。
一般格式为:数据类型 * 指针名;
以上为指针的定义。指针名是一个标识符,跟所有变量标识符命名规则一样。根据定义时的数据类型不同,指针同样分为如整型指针,字符型指针,实型指针,等等类型。不同指针类型对应不同变量,即只能指向相对应数据类型的变量。
本质上,指针也是一个变量,只是该变量的值是一个地址,是它指向的目标变量的地址。另外一点,由于指针的值是内存空间的地址,用sizeof()函数可以发现,无轮定义指针时时实型,整型还是浮点型,指针的长度都为4,因为内存地址4个几节足以存储。这也是指针的特殊性之一。
指针的算术运算:
包括加减,自加,自减几种。
指针的算术运算的结果是指针指向的地址相应移动一个变量的位置。比如原指向一个整型变量,则执行++运算后,指针指向的地址值将增加4,即4个字节。以此推论,如果指针原指向一个字符变量,++后,指针指向的地址的值只增加1。
//指针的算术运算
int a;
int *p=&a;
//p=&a;
char b;
void *p1=&b;
cout <<"运算前整型指针p的值为:" << p << "\t" << "运算后整型指针p的值为:" << ++p << endl;
cout <<"运算前字符指针p1的值为:" << p1 << "\t" << "运算后字符指针p1的值为:" << ++p1 << endl;
return 0;
运行结果为:
指针和数组
指针和数组什么关系?据说是好基友。学完指针,我对数组的理解也更深刻了。
int a[5];
int *p=a;
cout << sizeof(p) << endl;
cout << p<< endl;
cout << a << endl;
最后一行代码直接输出数组名a,我们会发现,a的值其实是一个地址。。。事实上,a确实代表了数组a[]的首地址(可以把数组名看作一个指向该数组首位元素地址的指针,不过该指针是不可更改的,与指针变量是有区别的),数组作为一个连续空间内存的变量,又可以通过指针直接指向a的值(是不是像指针指向来指针),联想到指针的算术运算,整个数组用指针来操作实在是再方便不过了。。。
比如用指针对一个空的数组赋值:
int a[7];
int *p=a;
for(int i=0;i<7;i++)//此处直接把i的值依次赋给数组元素
{
*p=i;
p++;
}
p-=7;//指针重新回到数组首位
for(int j=0;j<7;j++)//输出数组
{
cout << *p << endl;
p++;
}
其它操作自行领悟。
注:指针是个好东西,也是个危险的东西。由于指针可以通过算术运算任意改变指向位置,一旦编写时有逻辑错误,让指针指向了它本不该指向的地方。此时若通过指针修改了对应地址的值,嗯。。。
用指针来理解二位数组乃至多维数组
一维数组很好理解,计算机中一块连续的内存空间,反应的也是一系列相同类型的数据。
先上代码:
//二维数组和多维数组
int a1[5][6];//定义一个二维数组
int *p=0;//指针定义为空
int t=0;
for(int i=0;i<5;i++)//循环赋值
{
for(int j=0;j<6;j++)
{
a1[i][j] = t;
t++;
}
}
for(int i=0;i<5;i++)//按行列打印看数组赋值效果
{
for(int j=0;j<6;j++)
{
cout <<a1[i][j] << "\t\t";
}
cout << endl;
}
cout << endl;
//尝试把a1[0][0]的地址赋值给指针p,成功。
//并且当指针p成功被赋予二维数组的第一个地址后,随着指针的自增,我们可以看到,取指针指向地址的值跟二维数组元素的值意义对应
//这验证了二维数组在计算机内存中实际上是通过一维的方式即链式存储的。
p=&a1[0][0];
for(int i=1;i<=30;i++)
{
cout << *p << "\t";
if(0 == i%10) cout << endl;
p++;
}
cout <<endl;
//再来定义一个简单的5维数组,进一步验证其在计算机中的物理存储方式
int a2[2][2][2][2][2];
for(int i=0;i<2;i++)//同样循环赋值
{
for(int j=0;j<2;j++)
{
for(int k=0;k<2;k++)
{
for(int l=0;l<2;l++)
{
for(int m=0;m<2;m++)
{
a2[i][j][k][l][m] = t;
t++;
}
}
}
}
}
for(int i=0;i<2;i++)//循环打印,可以看到该数组值从30到61,总共32个元素
{
for(int j=0;j<2;j++)
{
for(int k=0;k<2;k++)
{
for(int l=0;l<2;l++)
{
for(int m=0;m<2;m++)
{
cout << a2[i][j][k][l][m] << "\t\t";
} cout << endl;
} cout << endl;
} cout << endl;
} cout << endl;
}
cout << endl;
//首地址赋值给p
p=&a2[0][0][0][0][0];
for(int i=1;i<=32;i++)//再次通过p指针来查看值,同样是30到61之间的32个数,符合预期。
{
cout << *p << "\t";
if(0 == i%10) cout << endl;
p++;
}
可以发现,无论是一维数组还是多维数组,其元素的物理存储方式均是线性连续的。
如何理解多维数组?
我在调试程序时,发现旁边的列表帮我们很好的理解了多维数组:
如图,a1为二位数组,a2是一个多维数组。二维数组是元素为一维数组的数组,那么三维数组是元素为二维数组的数组,如此类推。。。多维数组,无穷尽也。。。相当于n的n次方的n次方的n次方。。。