big*_*zer 1 c arrays state functional-programming side-effects
这个问题特别适用于数组。
在许多语言中,我会这样做:
#This is in python for simplicity:
def increment(mylist):
for i in mylist:
i += 1;
return mylist
mylist = {0,1,2,3}
mylist = increment(mylist)
Run Code Online (Sandbox Code Playgroud)
我尝试了几种在 C 中返回数组的方法,但没有一个像上面那样工作。看起来 C 根本就不打算以这种方式工作。相反,我必须这样做:
#include <stdio.h>
increment(int *myarray, int size) {
for(int i = 0; i < size; i++){
myarray[i] += 1;
}
}
int main(){
int myarray[4] = {0,1,2,3};
increment(myarray, 4);
}
Run Code Online (Sandbox Code Playgroud)
不用说,C 函数会更改数组的状态,因此是一个副作用函数。有充分的理由避免这种情况(这不是这个问题的主题)。
C 有没有办法避免这些类型的副作用?
请注意,在 python 中,对象是通过引用传递的。
def increment(mylist):
// mylist is a local reference to the original array
for i in mylist:
i += 1; // i is a local value: nothing is changed in mylist!
return mylist // returns a reference to the original (and unchanged...) array
Run Code Online (Sandbox Code Playgroud)
改变原始列表应该做什么:
def increment(mylist):
for i in range(len(mylist)):
mylist[i] += 1
// returning mylist is optional since the caller's list has been modified
Run Code Online (Sandbox Code Playgroud)
这与 C 中的完全相同
int *increment(int array[], int size) {
for (int i=0; i<size; ++i) {
array[i] += 1;
}
return array;
}
Run Code Online (Sandbox Code Playgroud)
但你可以用 Python 构建并返回一个全新的列表:
def increment(mylist):
return [i + 1 for i in mylist]
Run Code Online (Sandbox Code Playgroud)
这在 C 中无法轻松完成。惯用的方法是让调用者提供数组和大小(如上所述)或返回动态分配的数组:
int *increment(int array[], int size) {
int *new_array = malloc(size * sizeof(int));
for (int i=0; i<size; ++i) {
new_array[i] = array[i] + 1;
}
return new_array;
}
Run Code Online (Sandbox Code Playgroud)
并让调用者在完成转移所有权后释放返回的数组。