C语言的参数传递与返回值
C没有引用传递
C没有引用!C没有引用!C没有引用!重要的事说3遍。
|
|
用C编译器编译:
C++中才有引用
其实都是值传递
教材中通常讲值传递,地址传递,其实都是值传递,本质没有区别。所谓地址传递,不过传递的是地址值而已,遵循同样的法则,没有任何特殊。
比如传递进入一个指针,如果你又对指针值进行了修改,那么修改之后的任何改动都不会影响到外部了,因为这也是值传递,形参不过是实参的一个copy。所以如果想要通过指针对外部数据进行修改,而不要修改指针p本身,而是对*p进行操作。
返回数据的方式
由于C值传递的特性,再加上其自动变量都保存于栈中,作用域都只限于函数或语句块内,所以返回于函数中创建的数组、结构指针等都是没有意义的。
尝试编译, 将发出警告:
所以我们经常可以看到C函数参数经常带有很多指针,指向空的或者待修改的结构/数据,它们的作用不是用于传入信息,而主要是为了输出结果。
比如上一篇中提到的编译正则表达式的regcomp
函数:
|
|
第一个参数就是用来传入一个空的regex_t
结构的指针,这个函数的作用就是将这个结构填入编译结果,这个指针才是真正的”返回值”,而return则只是一个状态码。
其它一些高级OOP(如JAVA)语言是很不一样的,例如Java的对象(数组也是对象)保存在堆中,在哪里创建对象并不影响其生存期。所以Java可以直接返回在任何方法在创建的对象,而不用担心作用域问题。
1、直接返回值。适合基本类型,理论上返回结构也可以,但是返回大型结构会导致大量copy操作影响执行效率。
2、传入指针。这是C中常用的方法。
3、效仿高级语言,返回在局部方法中创建的堆指针。
|
|
方法3听起来错,不用在参数中传递一大堆指针。理论上也是可行的(如上),但是有一个问题,即内存的分配和释放会不在同一地点(一个函数内,一个在函数外,可能位于不同源文件),易导致内存泄漏,所以并不推荐使用。
实际上
的例子,也是在外部分配空间
后将指针传入的,那么如果这样行不行呢?
这很有迷惑性,地址传递嘛,应该可行吧?
实际不行,因为malloc
之后,preg就指向不同的地址了,与实参preg
失去了任何关联。或者说赋值 的是形参,实参仍然是未定义值。需要注意的一点是不仅C中存在这个问题,Java中也有这个问题,如果你想修改传入的对象,一定不要再次用new赋值。
如果一定要在函数外声明,在函数内malloc
,那么只能传入指针的指针,然后赋值给(*p)
了。
|
|
很复杂不是吗?所以,传入指针以接收结果是C中相对最好的方式了。