数组参数传递

C/C++ 数组作为参数传递 指针 引用 原创
2019-09-27 18:22:19
1点赞

syficy

码龄5年

关注
数组参数传递
普通传递
我们知道,普通函数参数传递的实质是将实参的值赋值给形参
例程序1.1

//1.1
void printdz(int a)
{
cout<<“函数里a的地址为”<<&a<<endl;
}
int main()
{
int a;
cout<<“主函数里a的地址为”<<&a<<endl;
printdz(a);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
运行结果:

主函数里a的地址为0x61ff1c
函数里a的地址为0x61ff00

一维数组传递
然而,由于在C和C++中数组不能直接复制,传递时只传递一个首地址,在函数中需要使用的时候再跟据首地址和下标去寻找对应的值。
至于为何数组不能直接复制,笔者在网上找到了两种解释,有所异同,读者可以自行鉴别。

1.是为了避免不必要的复制开销,因为数组的复制将导致连续的内存读与内存写,其时间开销取决于数组长度,有可能会变得非常大。
为了避免复制数组的开销,才用指针代替数组。因此C语言使得当数组作为实参传递给函数的时候,将退化为同类型的指针,再传递指针的值。
因此,在函数中修改数组值时,修改的是真的值。
2.当初开发C语言时为了可见性,dmr 在 C 语言里每个 operation都可以直接翻译为简单的汇编语句(指令),是 constant time。而数组赋值需要循环,一个 = 操作就不再是 constant time,这违背了初衷。
这也是 C 语言没有乘方运算符的原因,因为没有对应的汇编指令,实现乘方需要用循环。
后来 C 语言支持了 struct 的赋值,constant time 这一原则被打破了,这是后话。
下面,我们观察数组作为函数参数时的地址情况
例程序1.2

//1.2
void printdz(int a[])
{
cout<<“函数里a0的地址为”<<&a[0]<<endl;
cout<<“函数里a的地址为”<<a<<endl; //a本身即为指针 无需取地址符
cout<<“函数里a1的首地址为”<<&a[1]<<endl;
a[1]=2;
}
int main()
{
int a[10]={1};
cout<<“主函数里a的首地址为”<<&a[0]<<endl;
cout<<"开始的a1为 "<<a[1]<<endl;
printdz(a);
cout<<“函数里改过的a1 为”<<a[1]<<endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
运行结果

主函数里a[0]的首地址为0x61fee8 //void printdz(int a[10]) correct
主函数里a的首地址为0x61fee8
开始的a1为 0
函数里a[0]的地址为0x61fee8
函数里a的地址为0x61fee8
函数里a1的首地址为0x61feec
函数里改过的a1 为2
请按任意键继续. . .

在这里我们可以看到函数里的首地址a[0]与主函数的首地址是相同的。且a已经是一个指针了。
由于是通过指针传递,因此无法得到数组的长度。
除了退化为指针传递,还可以直接通过指针传递和通过引用传递。

通过指针传递:
例程序1.3

void printdzyy(int *aa) //传入指针 or void printdzyy(int aa[])
{
cout<<“函数里参数的地址为”<<&aa[0]<<endl;
}
int main()
{
int a[10]={1};
int b[5]={1};
cout<<“主函数里a[0]的首地址为”<<&a[0]<<endl;
printdzyy(a);
printdzyy(b);//传入指针时 编译器无法知道数组长度 因此可以随便传
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
1
2
3
4
5
6
7
8
9
10
11
12
13
通过引用传递:
例程序1.4

//1.4
void printdzyy(int (&aa)[10]) //引用就可以传递数组长度 因此需要写出数组大小
{
cout<<“函数里aa的地址为”<<aa<<endl;
}
int main()
{
int a[10]={1};
int b[5]={1};
cout<<“主函数里a[0]的首地址为”<<&a[0]<<endl;
printdzyy(a);
//printdzyy(b); incorrect //如果传入b则编译不通过
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
1
2
3
4
5
6
7
8
9
10
11
12
13
14
如1.3 1.4程序可知,传入指针时,编译器无法知道数组长度,因此可以传递进去不同长度的数组,也可以不写出数组长度。但是传递引用时,同时将数组长度也传递进去了,所以传入时必须为相应长度的数组。并且,在传递引用时,需要注意用()将&aa括起来,否则编译器报错。
对于引用,也叫“别名”,某种意义上可作为无地址的指针,相比指针,引用不存在地址,必须被初始化,不存在NULL,不可改变对象,引用无法被多重引用。因此更加安全。

二维数组传递
可以理解为数组的定义等同于指针的定义,即*a等同于a[],因此可以作如下变换

//1.5
void func1(int iArray[][10]) //等同于 void func1(int (iArray)[10])
{} //等同于void func1(int iArray[10][10])
int main()
{
int array[10][10];
func1(array);
}
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
注意
(iAarray)可通过,去掉括号会编译错误

由于二维数组在栈内分配的内存是连续的,需要告诉编译器偏移的点,所以第二维度不可省,必须符合,而第一维度如一维数组一样随意。因此在上述代码1.5 中void func1(int iArray[9][10])不会报错,而void func1(int iArray[10][9])会报错。

同一维数组,这边推荐使用引用,使用引用时需要保证两个维度都要ok:

//1.6
void func3(int (&pArray)[10][10])
{ }
int main()
{
int array[10][10];
func3(array);
}
1
2
3
4
5
6
7
8
1
2
3
4
5
6
7
8
也可以指针的指针来表示二维数组,动态分配内存的形式,此时,严格来说,并不是二维数组。
此处代码源于 https://www.cnblogs.com/L-Lotus-F/p/4377998.html

#include
#include <stdio.h>
void out(double **a,int m, int n)
{
int i, j;
double b=0.0;
for(i=0; i<m; i++)
{for (j=0; j<n; j++)
{
a[i][j] = b;
b += 1.2;
printf("%5.1f",a[i][j]);
}
std::cout << std::endl; }
}
int main(int argc, char * agrv)
{
int i, j, m=2, n=3;
double *a;
a = new double
[m];
for (i=0; i<m; i++)
a[i] = new double[n];
out(a,m,n);
return 1;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
总结
在传递数组参数时,首要推荐通过引用来传递参数,精准传入数组大小值,函数中参数定义为 vtype (&name)[size][size],引用时传入名字即可。

在通过指针传递时,需要另外传入参数来传递数组的大小。

C++ —— 数组/指针 做为函数参数传递
#include <vector> #include <iostream> using namespace std; void fun1(int *a) { printf(“1、int *a :%x %d\n”, &a, sizeof(a)); } void fun2(int a[2]) { printf(“2、int a[2] :%x %d\n”, &am…
APP打开
C++中的数组指针和指针数组
using namespace std; int main(){ //a) 一个整型数( An integer) int a; //b) 一个指向整型数的指针( A pointer to an integer) int *b; //c) 一个指向指针的的指针,它指向的指针是指向一个整型数( A pointer to a pointer to an …
APP打开
评论(1)
写评论

可爱是你码龄2年

真的很有用1年前
C++数组(指针)作为函数参数
本文的学习内容参考:http://blog.csdn.net/wwdlk/article/details/6322843 1.当用数组名作为函数参数时,函数的实参和形参都应为数组名(或者指针); Example1:有一个一维数组score,内放10个学生成绩,求平均成绩。 #include using namespace std; flo…
APP打开
C/C++ 数组作为参数传递 指针 引用
https://blog.csdn.net/qq_30600259/article/details/101551220
APP打开
C/C++指针与引用基本操作与应用(作为函数参数进行传递…_CSDN博客
形参相当于是实参的“别名”,对形参的操作其实就是对实参的操作,在引用传递过程中,被调函数的形参虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调…
c++之指针作为函数参数传递的问题_wang386476890的专栏-CSDN博客
前段时间写了一篇文章《C++之 数组与指针的异同》对C 和C ++中的指针做了一个初步的讲解。这次将讲解一下指针作为函数参数传递的问题。
C++中数组名、指针的引用传递
int (&b)[5] = a; 一直以来我都认为只有在进行函数的参数传递时才会使用到引用传递,后来发现引用传递也可以在普通的代码中使用,相当于给变量增加了一个别名,如下面的代码: #include using namespace std; int main() { int a = 20; int &b = a; b++; cout << a; return 0; }
APP打开
C/C++中多维数组指针作为函数参数传递程序
在C++中,通过多维数据的指针作为函数参数传递源程序
APP打开
C专家编程–指针和数组(三) 值传递 指针传递 引用传递
在C++中,指针和引用经常用于函数的参数传递,然而,指针传递参数和引用传递参数是有本质上的不同的: 指针传递参数本质上是值传递的方式,它所传递的是一个地址值。值…
C/C++语言函数参数传递:传值,传指针,传引用_u012713968…_CSDN博客
传引用是C++里面引入的一种参数传递方法。传引用实际上也是传递的实参的指针,所以能够修改实参的值。 但是,引用的特性告诉我们,一旦引用初始化后,这个引用就不能再…
C语言中的引用,以及传递引用,数组传递
详解c++指针的指针和指针的引用 以下参考自:https://www.cnblogs.com/li-peng/p/4116349.html 展示一下使用指针的指针和指针的引用修改传递给方法的指针,以便更好的使用它。(这里说的指针的指针不是一个二维数组) 为什么需要使用它们 当我们把一个指针做为参数传一个方法时,其实是把指针的复本传递给了方法,也可以说传递指针是指针的值传递。 如果我们在方法内部修改…
APP打开
C与C++关于与&(引用方式传参,传值方式传参)
一个例子 补全该代码: 用C++: 用C:是把地址传进去,然后用
运算取地址的内容 、 1、引用方式传参,引用相当于是外部变量的别名,实际操作的就是该变量,即在函数内对该变量进行修改的话,在外部该变量也会相应被修改。 void ChangeRef(int& ref); 2、传值方式传参,实际上是复制了一个外部变量的副本进入函数中,在函数内操作的为该副本,对该变量的修改…
APP打开
C++函数的参数三种传值方式为:值传递、地址传递(指针传递,引用传递)
(1)指针传递与引用传递的区别: 指针参数传递本质上是值传递,它所传递的是一个地址值。值传递过程中,被调函数的形参作为被调函数的局部变量处理,会在栈中开辟内存…
C++指针、数组、引用、变量作函数参数_C/C++_犀利虫的专栏-CSDN博客
那么我们可以了解到指针,数组,引用其实都是指针。 那么指针做参数和普通变量做参数有什么区别呢。 其实不管是指针还是变量,在作为函数参数时都是值传递的。 比如…
C++传递数组指针的引用,不需要new,但是一定要初始化
#include “mainwindow.h” #include #include struct PDWS { PDWS(){TOA = 0;PW = 0;} PDWS(double toa,float pw){TOA = toa;PW = pw;} double TOA; float P…
APP打开
C/C++ 数组作为参数传递 指针 引用——VS——普通值传递、指针传递、引用传递
文章目录1 C++ 值传递、指针传递、引用传递详解值传递:指针传递:引用传递:2 数组作为函数的形参2.1 一维数组传递2.2 二维数组传递总结 1 C++ 值传递、指针传递、引用传递详解 值传递: 形参是实参的拷贝,改变形参的值并不会影响外部实参的值。从被调用函数的角度来说,值传递是单向的(实参->形参),参数的值只能传入,不能传出。当函数内部需要修改参数,并且不希望这个改变影响调用者时,采用值传递。 指针传递: 形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作
APP打开
写评论

1

1

1

分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值