1.通过数组和下标实现的表达式可以等价的通过指针和偏移量实现。
例如:
int a[]= {1,4,66,8};
*p = a;
p = &a[0];//和上面一句等价
*(p+1) 和a[1]和*(a+1)是等价的
a+1和&啊&a[1]也是等价的。
2.数组作为函数参数在传参时会自动退化为普通指针
int Srlen(char string[]);
在此函数中若调用系统的字符串长度函数sizeof会发现算不出正确的字符串长度
int Size(char string[])
{
return sizeof(string);
}
int _tmain(int argc, _TCHAR* argv[])
{
char pStr[] = {'a','b'};
cout<<sizeof(pStr)<<endl;
cout<<Size(pStr)<<endl;
return 0;
}
得出结果为2,4
数组是一个完备的变量类型,有名字、大小、地址,只不过名字和它的首地址一样罢了,所以用sizeof对数组名
进行计算时算出的是实际数组的大小,而不是指针大小。
3.c/c++默认的是值传递,这个是临时想起来的,也放到这篇里了
double *p = NULL;
fun(p);
if (p == NULL)
{
cout<<"p not changed"<<endl;
}
else
{
cout<<"p changed"<<endl;
}
结果为:p not hanged
如果想要改变指针的值还是要址传递参数,这里很容里犯错。下面是正确的做法
double* fun(double **p)
{
*p = new double;
return *p;
}
int _tmain(int argc, _TCHAR* argv[])
{
double *p = NULL;
fun(&p);
if (p == NULL)
{
cout<<"p not changed"<<endl;
}
else
{
cout<<"p changed"<<endl;
}
getchar();
return 0;
}
4.二维数组的等价访问方式
数组名是一个const指针。
再次强调
数组是一个完备的变量类型,有名字、大小、地址,只不过名字和它的首地址一样罢了,所以用sizeof对数组名
进行计算时算出的是实际数组的大小,而不是指针大小。也正是因为如此,指向数组的指针指向指针有些不一样
最明显的不同就是表现在指针进步的时候我们知道指针在++进行运算的时候,跨越的实际地址取决于指针指向的
数据类型。例如在32位字长机器中指向int型数据跨越的实际地址是4,指向指针类型也是4.指向数组类型的时候,
跨越的实际地址就是数组的长度了。
int a[3][3] = {1,2,3,4,5,6,7,8,9};
下面三种初始化或者复制方式都会编译出错:
int **p = a;
int *p = NULL;
p = &a;
下面两个是正确的:
p = &a[0][0];
int (*q)[3] = a; //指向含有三个元素的数组的指针,下面会介绍
再看看用这两个正确的方式如何访问数组元素
遍历:
//用p来遍历二维数组
for (int i = 0;i < 12;i++)
{
cout<<*(p++)<<endl;
}
//用q来遍历二维数组
for (int i = 0;i < 4;i++)
{
for (int j = 0;j < 3;j++)
{
cout<<q[i][j]<<endl;
}
}
看看下面输出的是什么:
for (int i = 0;i < 4;i++)
{
cout<<q[i]<<endl;//这里i++或者q++一次就是移动了三个整形元素数组的空间
}
是a[0][0]、a[1][0]、a[2][0]、a[3][0]的地址
下面就很清楚了:
for (int i = 0;i < 4;i++)
{
cout<<*q[i]<<endl;
}
输出的是a[0][0]、a[1][0]、a[2][0]、a[3][0]的值
首地址a也可以像q一样访问数组元素:
int a[4][3] = {1,2,3,4,5,6,7,8,9,10,11,12};
for (int i = 0;i < 4;i++)//a++有一样的效果
{
cout<<a[i]<<endl;
cout<<*a[i]<<endl;
}
输出:
看看下面代码的输出
int a[4][3] = {1,2,3,4,5,6,7,8,9,10,11,12};
for (int i = 0;i < 4;i++)
{
for (int j = 0;j < 3;j++)
{//输出每一个元素的地址和值
cout<<&a[i][j]<<" "<<a[i][j]<<endl;;
}
}
for (int i = 0;i < 4;i++)
{
for (int j = 0;j < 3;j++)
{
cout<<((*a+i)+j)<<endl;
cout<<(*a+i+j)<<endl; //这就相当于用*a取得首地址,后面再加就相当于是在处理一维数组指针,跟前面的p一样
//cout<<*((*a+i)+j)<<endl;
}
}
输出:
for (int i = 0;i < 12;i++)
{
//从头到尾遍历每个元素的地址和值
cout<<(*a+i)<<" "<<*(*a+i)<<endl;
}
输出:
5.如何new一个二维数组(动态创建二维数组)
int row = 0;
int column = 0;
cin>>row>>column;
int **p = new int*[row];
int k = 1;
for (int i = 0;i < row;i++)
{
p[i] = new int[column];
for (int j = 0;j < column;j++)
{
p[i][j] = k++;
}
}
int *q = &p[0][0];
for (int i = 0;i < row*column;i++)
{
//因为此处p这个二维数组是new了两次创建的,里面的元素不是像a[4][7]一样在内存中
//顺序排列的,所以用这种方法无法正常打印出二维数组的值
cout<<(q+i)<<endl;
cout<<*(q+i)<<endl;
}
//下面是一种遍历动态创建的二维数组的正确方法
for (int i = 0; i < row;i++)
{
for (int j = 0; j < column;j++)
{
cout<<p[i][j]<<endl;
}
}
上面代码运行结果如下:
6.指针数组与数组指针
//()的优先级高,首先说明q是一个指针,指向一个整型的一维数组,这个数组的长度为4。
int (*q)[4] = a;//指向含有4个元素的数组的指针,q++每次移动一行
//[]的优先级高,先与p结合成一个数组,再由int*说明这是一个整型指针数组,它有3个整数指针类型的数组元
int *p[3] = {&a[0][2],&a[1][0],&a[2][0]};//指针数组,顾名思义就是存放指针的数组,就像定义普通数组一样