指针可以说是C语言中最难理解的部分,因为它涉及的内存单元和变量较多,今天重新整理了一下数组与指针的内容。
指针与一维数组
int a[10] = {1,2,3,4,5,6,7,8,9,10};
int * p = a;
这里 ptr_int = &a;
这样的意思是
a是数组名,同样是数组的首地址,也就是数组的地址(数组以连续存储单元存放)。
ptr_int + 1 就是指一次移动四个字节(即一个int型大小);
a + 1 就是指向 a[1] , 即a + 1 = &a[1];
遍历数组的方法:
1.
for(int i = 0;i < 10;i++)
{ cout << a[i] <<'\t' ;
} //这里a[i]就是每一个数组元素的值
for(int i = 0;i < 10;i++)
{ cout << *(p + i) << '\t';
} //这里 p指向 a[0],p+i指向a[i],*(p + i)就是取p+i指向的值,正是数组元素
for(int i = 0;i < 10;i++)
{ cout << *(a + i) <<'\t' ;
}//这里 a就是数组地址,指向a[0],a+i指向a[i],同上;
指针与二维数组
一个最容易理解的也是最普遍的方法是 将二维数组看成一个一维数组,特殊之处在于 这个一维数组的每一个元素也是一个一维数组,例如
int a[3][4] = { {1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
这里 将a看成一个一维数组,一维数组里面有三个数组元素,即a[0],a[1],a[2].
a[0] = {1,2,3,4}
a[1] = {5,6,7,8}
a[2] = {9,10,11,12}
从外向内分析,a 是一维数组名,是数组首地址,是数组地址(因为数组在内存单元中以连续内存存储,即物理结构连续).
如果
int* p = a;
这样的话 a = &a[0];
p = &a[0];
*p = a[0];
p + 1= &a[1];
*( p + 1) = a[1];
你会发现这里与一维数组一模一样,这样的话遍历数组就要看内层。
拿第一个数组元素为例,也就是a这个一维数组中第一个数组元素a[0];
a[0]是一个一维数组, 是一维数组的首地址,是一维数组的地址
a[0] = &a[0][0]
a[0] + 1 = &a[0][1]
与外层放在一起就是
a[0][1] = *(a[0] + 1) = *(*p + 1);
这就是整个推导过程。
同样
a[1] = &a[1][0]
a[1] + 1 = &a[1][1]
与外层放在一起就是
a[1][1] = ((p + 1) +1);
这样就不难理解为什么说行指针前面加取值符号就是列指针,因为行指针本身也可以看做地址,是列元素的地址。
这样遍历整个二维数组就可以实现如下:
1.
for(int i = 0;i < 3;i++)
{ for(int j = 0;j < 4;j++)
{ cout << a[i][j] << '\t';//直接访问数组元素
cout << endl;
}
}
for(int i = 0;i < 3;i++)
{ for(int j = 0;j < 4;j++)
{ cout << *(a[i] + j) << '\t';//从行的变化来访问
cout << endl;
}
}
for(int i = 0;i < 3;i++)
{ for(int j = 0;j < 4;j++)
{ cout << *(*(p + i)+ j) << '\t';//先取行,在取值变成列的地址,再取
//值,变成列的值;
cout << endl;
}
}
需要注意的是,在这个里面 a + 1移动的字节数,一个二维数组元素是4个字节,一行是一个元素,就是 4 * 4 = 16个字节。
所以遍历也可以写成
*(a[0] + 4 * i + j)
或者
*(&a[0][0] + 4 * i + j)
以上就是大概的内容,最好的掌握指针的办法就是多用!!!!