分类: C/C++
2011-03-10 10:52:16
1·数组传递并不会进行数组数据的copy,只会传递数组的首指针。
普通数组作为参数就是传指针呀,不会复制的。
参数中的数组就变成指针了,所以如果想要知道各维的大小只能通过参数把维数传进去,别无它法
2·数组是不能做参数的,我感觉是表达错误?!只要是人就会犯错误
意思明白就行了,小数据可以直接传,大型数据一般用引用或指针(const保护)
3·C++ Primer (4th Edition)中的7.2.2.节中有句话是不是说错了
在看到用const引用避免复制时有这么一句话: The other circumstance in which reference parameters are useful is when passing a large object to a function. Although copying an argument is okay for objects of built-in data types and for objects of class types that are small in size, it is (often) too inefficient for objects of most class types or large arrays.
中文翻译是: 在向函数传递大型对象时,需要使用引用形参,这是引用形参适用的另一种情况.虽然复制实参对于内置数据类型的对象或者规模较小的类类型对象来说没有什么问题,但是对于大部分的类类型或者大型数组,它的效率(通常)太低了.
请问这里的large arrays(大型数组)用于函数形参时,可以用对应的实参初始化吗? 如果调用这样的函数,则必须要对实参复制吧,而书中前面有明确的说过:数组不能复制. 这不止是效率的问题, 就算是小型数组也不能通过编译啊.
4·数组作为形参,和接受它的实参有以下的关系:
1.形参和实参都是数组名。
2. 实参用数组,形参用指针变量.
3. 实参、形参都用指针变量。
4. 实参为指针变量,形参为数组名。
在C语言中,数组名是当作指针来处理的。更确切的说,数组名就是指向数组首元素地址的指针,数组索引就是距数组首元素地址的偏移量。理解这一点很重要,很多数组应用的问题就是有此而起的。这也就是为什么C语言中的数组是从0开始计数,因为这样它的索引就比较好对应到偏移量上。在C语言中,编译过程中遇到有数组名的表达式,都会把数组名替换成指针来处理;编译器甚至无法区分a[4]和4[a]的区别。
我们在题中定义了
int a[10];
int *b;
这两者并不等价,第一句话声明了数组a,并定义了这个数组,它有10个int型元素,sizeof(a)将得到整个数组所占的内存大小,是40;第二句话只是声明并定义了一个int型的指针,sizeof(b)将得到这个指针所占的内存大小,是4。所以说,虽然数组名在表达式中一般会当作指针来处理,但是数组名和指针还是有差距的,最起码有a==&a[0]但是sizeof(a)!=sizeof(a[0])。
并且在ANSI C标准中,也明文规定:在函数参数的声明中,数组名可以当作指向该数组第一个元素的指针。所以,下面的几种书写形式是等效的:
void func1(int arr[]){}
void func2(int *arr){}
对于第一种还可以写成void func1(int arr[100]){},在形参中其实不需要指定数组的大小,因为其实在这几个函数在函数调用时传入的只是一个该数组的指针,想要确定几行几列的话还需要另外定义参数进行传入.如果在使用该指针的过程中不清楚原数组的范围,指针很容易就越界,内存也就溢出了。
当用数组名作函数参数时,形参数组就可以从实参数组那里得到起始地址后,形参数组就和实参数组共占同一段内存单元,从而在调用函数期间,如果改变了形参数组的值,也就该变了实参数组的值。
最后要补充一点,也就是上次我们学员问我的一个问题,作为形参int arr[]和int *arr有什么区别。在本质上,我们看通过程序,貌似真的没有区别,虽然arr[]是作为数组传递进去,但是我们也可以修改arr的指向,而作为实参的数组的a却不能使其加一。我们都知道函数之间的参数传递有:复制传递方式、地址传递方式、全局变量。
那么姑且就将void func1(int arr[])最为函数按复制传递的方式,而void func2(int *arr)作为其地址传递的方式。而复制传递方式与数组的指针传递方式是完全相同,只是形参的说明形式不同而已。调用函数将实参数组传递给被调用函数形参,形参接收是实参的地址。不论哪种方式,被调用函数里对形参数组的操作都会影响调用函数里的实参数组。