指针类型的形参(26)

指针参数

实参与形参是一种赋值关系(引用除外)。指针参数可以分为两种情况:指针做为实参赋值给形参,除特殊情况下,形参应该是与实参相同类型的指针;另外一种情况则是实参可能是数组等类型,形参则可能是一些特殊的指针类型。

一维数组情况

一维数组和指针都是一种线性关系,基本上可以通用

#include <iostream>
#include <stdio.h>
using namespace std;
void fun(int *x)  //void fun(int x[10])
{
	int i;
    //cout<<sizeof(x)<<endl;
	for(i=0;i<10;i++)
		x[i]=i;
}
int main()
{
	int a[10];
	int i;
	fun(a);
	for(i=0;i<10;i++)
	{
		cout<<a[i]<<" ";
	}
	cout<<endl;
	return 0;
}

函数定义形参可以是指针,也可以是数组,其实就是指针;用sizeof(x)可以看到不管是指针还是10元素的数组,都是4个字节;结论应该形参应该是指针。

实参肯定用数组名,其他方式都不可能符合语法:a[10]肯定不行,没有这个元素(0~9)。同样也可以验证形参应该是指针,指针保存地址,数组名是首地址。

数组不一定写成 int a[10],甚至可以写成其他尺寸大小的数组:void fun(int x[5]) 语法可以通过,运行结果都一样,进一步验证了把形参统一成指针,程序员保证数组不越界访问。

二维数组、二维指针、指针数组、数组指针

二维数组具有指定的二维结构,并且按照一维的方式进行物理存储,也就是说物理上所有元素在连续的内存空间里,逻辑上有行列下标特点;

二维指针是指向指针的指针变量,它保存的是另一个指针的地址;

指针数组本质上是数组,它的每一个元素都是指针,逻辑上具有下标特点;

数组指针本质上是指针,是一种特殊的指针,它保存一个指定尺寸的数组的(首)地址。

从上面描述,可以看看相互强制转换:

1、二维数组转换成一维指针,是可取的:物理上本来就是一维的结构,但逻辑上的行需要通过一维指针的计算来实现;

#include <iostream>
#include <stdio.h>
using namespace std;
void fun(int *x)
{
	int i,j;
	for(i=0;i<5;i++)
		for(j=0;j<4;j++)
		// *(x+4*i+j) =i * j;
	     x[4*i+j]=i * j;
}
int main()
{
	int a[5][4];
	int i,j;
	fun((int *)a);
	for(i=0;i<5;i++)
	{
		for(j=0;j<4;j++)
		   cout<<a[i][j]<<" ";
		cout<<endl;
	}
	return 0;
}

强制转换的依据是 物理实现的连续性: x[ i * 4 + j ]  第几行第几列要算清楚;另外下标的方式和指针取值的方式是等价的。

2、二维数组与二维指针,二维数组具有行地址的特点,数组名   a  +  i 是第i行的起始地址,与行的大小相关;二维指针则认为保存的是另一个指针的地址。

下标操作肯定无法满足要求:二维数组先通过行下标找行,二维指针则是加一个指针变量的大小,4个字节。

然后,取内容操作必须要把二维指针看成是一维指针,再通过上面的方法来实现。

void fun(int **x)
{
	int i,j;
	for(i=0;i<5;i++)
		for(j=0;j<4;j++)
		 *((int *)x+4*i+j) =i * j;	   
}

函数调用时:fun((int **)a);  强转

3、二维数组与指针数组:两个都是数组,逻辑上指针数组是一维的,每个元素都是一个指针。强制转换是不成立的。要说明的它们的区别:指针数组可以通过下标找到每个元素,而每个元素都是一个指针,所以有时候可以用二维数组的行列下标来实现对元素的引用;

int main()
{
	int a[2][3]={1,2,3,4,5,6};
	int *x[2];
	int i,j;
	for(i=0;i<2;i++)
		x[i]=new int[3];
	for(i=0;i<2;i++)
		for(j=0;j<3;j++)
			x[i][j]=a[i][j];
	for(i=0;i<2;i++)
	{
		for(j=0;j<3;j++)
			cout<<x[i][j]<<" ";
	     cout<<endl;
	}
	return 0;
}

new是动态分配空间,定义数组是静态分配空间: int  x[3];区别是new在堆区,程序员控制回收,局部变量数组则是在栈区。上面代码可见,指针数组确实可以具有二维的结构,每个元素都是指针,指针当然可以指向一个数组。

指针数组与二维数组的区别当然也很明显:首先,指针数组的元素是指针,是一个个变量可以赋值;而二维数组的行地址是常量;然后,指针数组的元素可以指向一个数组,也可以指向其他的普通变量,二维数组当然不行(也就是说指针数组的下标操作是有风险的);最后,即使是指针数组的每个元素都指向一个数组,每个元素指向的数组大小可以不相同的,每行存放的位置也可以不连续,也就是说每行长度不一,每行也不需要连续存储。

结论:指针数组下标引用有风险。

4、二维数组与数组指针:它们的关系是一维数组和指针的关系,也就是可以通用,不需要强制转换。数组指针是一个特殊指针,正好保留了二维数组的行列特点。数组指针指向的是一个特殊数组,加法运算应该是加特殊数组的大小,正好满足行地址的操作!

 结论:二维数组和数组指针通用,最好用这种方式进行参数传递。

#include <iostream>
#include <stdio.h>
using namespace std;
void fun(int (*x)[4])
{
	int i,j;
	for(i=0;i<5;i++)
		for(j=0;j<4;j++)		
	     x[i][j]=i * j;
}
int main()
{
	int a[5][4];
	int i,j;
	fun(a);
	for(i=0;i<5;i++)
	{
		for(j=0;j<4;j++)
		   cout<<a[i][j]<<" ";
		cout<<endl;
	}
	return 0;
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

易老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值