关于C语言中数组作为参数传递的疑惑~~
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于C语言中数组作为参数传递的疑惑~~相关的知识,希望对你有一定的参考价值。
int array[]=1,2,3
void a(int array[2])
void b(int array[])
void c(int (&array)[2])
以上都是以数组作为参数传递给函数a,b,c的。想了解以上三者的区别,希望各位老大详细解释,谢谢~~~
先看代码:
#include <stdio.h>
void foo(int array[2])printf("int array[2]:\t\t%x %d\n", &array, sizeof(array));
void bar(int array[])printf("int array[]:\t\t%x %d\n", &array, sizeof(array));
void baz(int (&array)[2])printf("int (&array)[2]:\t%x %d\n", &array, sizeof(array));
int main()
int a[2] = 1, 2;
printf("main::a[2]:\t\t%x %d\n", a, sizeof(a));
foo(a);
bar(a);
baz(a);
return 0;
解说:
foo和bar的传值方式是相同的,都是一个int*, 即一个整型指针,这可以从foo和bar里打印出的array地址和main中的不同和sizeof(array)仅为sizeof(int*)看出,只不过是外型有点儿区别。
编译器是不知道你要传递的是一个数组或是单一一个整型的地址的,这是因为C中数组的内存模型是连续存储(它并不知道传递的(首)地址之后的空间可否访问)。
所以写为foo或bar的样式仅仅是对人的一种暗示,暗示传递的是一个数组,括号里的2编译器是不会把他当回事儿的①。
采用foo中的样式,代码编写者在函数中获知传递的数组的大小,但这种暗示功能很弱,而且易使人产生误解。
比如以上的函数foo,传递大小为1个元素的数组(即单一一个整型的地址):
int x[1];
foo(x);
或传递一个大小为100的数组:
int x[100];
foo(x);
编译器都不会有任何抱怨,所以在代码工程量很大的时候,你无法保证数组传值的安全性,另外一个问题是如果你写的是商业性质的库,你无法保证客户(二次开发者)能安全地使用你的代码。
采用bar中样式,实质和foo相同,空括号给人的暗示就是它能接受的参数是一个数组,而且是一个长度不确定的一维整型数组,这相对于foo来说更为实际和真实一些(因为foo可能造成欺骗性的代码,原因见上)。
所以这种传数组的方式被多数人所采用,但一般还需多加一个参数来指定数组的大小,如:
void bar(int array[], int size);
或效仿STL的做法,传递数组的首地址和超尾指针(在遍历数组元素时很方便,且更快速、安全):
void bar(int* beg, int* end);
至于baz,它不同于foo和bar。前面已经说过,foo和bar实质是相同的,传的都是一个int*,且传值方式都是按值传递(C中只有按值传递)。
而baz却是按引用传递,传递的是一个"编译器认可的,大小为2"②的数组的引用。
foo和bar都可以改写为:
void theFact(int* array);
或
void theFact(int* array, int size);
按照此逻辑是不是baz可改写为这样呢?
void baz2(int* const& array); // a其实是一个int* const型指针,所以要加上const作为修饰
答案是否定的,注意上面的②,只有在C++中,函数"按引用"传递数组并"指定其大小时",[]中的数字才有意义(对编译器而言)。所以baz2 != baz:
int x[100];
baz(x); // 编译错误
baz2(x); // 可以通过
要理解这和foo, bar的不同首先要理解C++中对引用的定义: 引用就是对象本身,不存在没有引用对象的引用。所以在baz中,形参array就是实参main中的a,一切a所有的特性都是array的特性,所以sizeof(array) == sizeof(a),而且&baz::array == main::a(地址相同)。
①: C99中允许使用static数组参数修饰词,如:
void foo(int x[static 10]); // x数组至少含有10个连续元素
上句中的10此时并不是可有可无的,它是编译器优化数组访问的一种暗示。 参考技术A C语言数组调用是传送地址调用。
为便于弄清函数原型和数组调用,把程序补充写成:
#include<stdio.h>
#include<stdlib.h>
void a(int x[2]) x[0] = 11; x[1] = 12; ;
void b(int x[], int n)
int i;
for (i=0;i<n;i++) x[i] = 2.0 * x[i];
void c(int x) printf("%d\n",x);
void main()
int array[]=1,2,3 ;
int k;
(void) a(array);
printf("%d %d %d\n",array[0],array[1],array[2]);
(void) b(array, 3);
printf("%d %d %d\n",array[0],array[1],array[2]);
k = (int) (&array)[2];
(void) c( k);
printf("%d %d %d\n",array[0],array[1],array[2]);
a(array); 调用,函数a 对调用数组前2个单元做了加工,第3个单元不做加工。所以输出结果 11,12,3
b(array,3); 调用,对array 3个单元做了加工,各乘2,
所以输出结果 22,24,6
c的调用是把array 的指针值拿来派用场,所以输出结果不变 22,24,6
如果a函数原型是 void a(int x),
调用(void) a(array[2]), 则是把数组第3个元素拿来加工。
因问题说得不清楚,只好猜测。本回答被提问者和网友采纳 参考技术B 1、数组做参数,完全无法按值传递。这是由C/C++函数的实现机制决定的。
2、传数组给一个函数,数组类型自动转换为指针类型,因而传的实际是地址。
下面三种函数声明完全等同:
void func(int array[10])
void func(int array[])
void func(int *array) 参考技术C 第一个函数是把数组array的第三个元素作为参数传递过去的,是传值;
第二个函数是把数组array的地址,也就是第一个元素的内存地址传递过去,是传址;
第三个,呃,不太明白了,如果没有那个圆括号,我会认为是传递的数组第三个元素的地址,但是加了这个括号代表什么呢,有点疑惑。 参考技术D 三个都是定义了没有返回值的函数
但是第一个是定义了一个有两元素就是说数组中的元素不能大于二而溢出的整形数组,将这个数组作为函数的参数
第二个没有定义元素的个数,同样将数组作为函数的参数
第三个则是定义了一个具有两个元素的指针型数组,传递的是数组的首地址
关于c语言中数组作为函数参数的函数之间调用问题
比如,在main函数中定义了一个int array[3]; 不赋初值
再写两个子函数,假如在第一个子函数中给数组赋值,在第二个子函数中用这个数组中的值做计算,就假设是在这里定义另一个数组 做 s[i]=array[i] *i;的操作好了。
……fun1 (……)
……
……fun2 (……)
for(i=0,i<n;i++)
s[i]=array[i] *i;
……
main()
……//fun1调用
……//fun2调用
我假设的问题有没有意义不重要,也不是要其他什么简便方法,我就是想知道这样关于数组在函数之间的调用是怎么处理的,返回值是怎么样的。可以的话给我一个完整的参考代码,谢谢~~~
1、新建一个数组作为参数项目,如图所示:
2、添加一个array.c文件,如图所示:
3、包含stdio.h和stdlib.h头文件,如图所示:
4、输入main函数主体及返回值,如图所示:
5、定义一个数组arr,如图所示:
6、定义一个function函数,如图所示:
7、将数组作为参数传递给function函数,如图所示:
8、运行程序,输出结果,如图所示:
参考技术A 这问题说明你对指针的运用还是不熟练的,既然是数组,作为函数参数传递的是数组首地址.#include <stdio.h>
#include <stdlib.h>
void func1(int *array, int size)
int i,temp;
for (i=0;i<size;i++)
scanf("%d",&temp); //利用scanf输入赋值
array[i]=temp;
//数组array_b根据数组array_a的元素乘以项数获得元素值
void func2(int *array_a,int *array_b, int size)
int i;
for (i=0;i<size;i++)
array_b[i]=array_a[i] * i;
//输出数组元素
void print(int *array, int size)
int i;
for (i=0;i<size;i++)
printf("%d ",array[i]);
printf("\n");
int main(void)
int size; //数组大小
int i;
int *array_a, *array_b; //声明数组array_a,array_b
scanf("%d", &size);
array_a=malloc(sizeof(int) * size);
array_b=malloc(sizeof(int) * size);
func1(array_a, size);
func2(array_a, array_b, size);
print(array_a,size);
print(array_b,size);
return 0;
本回答被提问者采纳 参考技术B 这问题说明你对指针的运用还是不熟练的,既然是数组,作为函数参数传递的是数组首地址.
#include
<stdio.h>
#include
<stdlib.h>
void
func1(int
*array,
int
size)
int
i,temp;
for
(i=0;i<size;i++)
scanf("%d",&temp);
//利用scanf输入赋值
array[i]=temp;
//数组array_b根据数组array_a的元素乘以项数获得元素值
void
func2(int
*array_a,int
*array_b,
int
size)
int
i;
for
(i=0;i<size;i++)
array_b[i]=array_a[i]
*
i;
//输出数组元素
void
print(int
*array,
int
size)
int
i;
for
(i=0;i<size;i++)
printf("%d
",array[i]);
printf("\n");
int
main(void)
int
size;
//数组大小
int
i;
int
*array_a,
*array_b;
//声明数组array_a,array_b
scanf("%d",
&size);
array_a=malloc(sizeof(int)
*
size);
array_b=malloc(sizeof(int)
*
size);
func1(array_a,
size);
func2(array_a,
array_b,
size);
print(array_a,size);
print(array_b,size);
return
0;
参考技术C 函数在数组中的调用是以数组名为实参调用的,因为数组名就是数组的首地址,所以说对数组的调用是不需要返回值的,主调函数里面的数组值会随被调函数的形参数组改变而改变,当然这些都是在你以数组名作为实参的前提下 参考技术D 如果传递值是指针(地址),也就是数组名,虽然在子函数里面,但复制过去的是地址,所以可以对地址里面指向的内容进行操作,也就是一个子函数中可以实现对多个值的操作,如果传递的是内容,则至多通过return 进行一个返回值操作,总之,要看你传什么
以上是关于关于C语言中数组作为参数传递的疑惑~~的主要内容,如果未能解决你的问题,请参考以下文章