How to send array by value to function in c?

2019-07-25 13:03发布

问题:

I tried something like :

typedef struct vec{
     int sz;
     int v[];
} ff;

int sum(struct vec z){
    int o=0,i;
    for(i=0;i<z.sz;i++)
        o+=z.v[i];
    return o;
}

int main(){
    int test[]={10,1,2,3,4,5,6,7,8,9,10};
    return sum((struct vec)test);
}

But this example code can't compile. How to send array by value (not ref throw pointer) to function?

回答1:

In your example, you will need to specify the exact size of the array in the definition of struct vec, for example int v[10]. Also your initialization can be written better. Try this:

#define MAX_SIZE 50
struct vec {
   int sz;
   int v[MAX_SIZE];
};

int sum(struct vec z){
  int i, o;
  o = 0;
  for(i=0; i<z.sz; i++) o += z.v[i];
  return o;
}

int main(){
  struct vec test = {10, {1,2,3,4,5,6,7,8,9,10}};
  return sum(test);
}


回答2:

You can't send an array by value in C. Every time you try to pass an array to a function, you'll pass the pointer to the first value.
To pass an array by value, you can cheat a little and encapsulate it in a struct, and send it by value (so it will be copied)... It's a dirty hack, as explained here, but well, if you really want that, it works.
Another way is to copy the array inside the function, with the pointer given.



回答3:

While it's true that an array in C has a size, that size can only be accessed through the sizeof operator, and then only on the original array. You can't cast an array to a structure in the hopes that the compiler will fill in all fields.

In fact, it's actually impossible to pass an array to a function "by value". All arrays decays to pointers, so when you pass an array to a function that function receives a pointer. This decay to pointers is also why you can only use the sizeof operator on the original array, once it decays to a pointer the compiler have no idea that it's actually pointing to an array, so using the sizeof operator (even on something that points to an array) will return the size of the pointer and not what it points to.

In your case, it would be simpler to change your function to take two arguments, the pointer to the array and the number of entries in the array:

/* `array` is an array containing `elements` number of `int` elements. */
int sum(const int *array, const size_t elements)
{
    ...
}

int main(void)
{
    ...
    printf("Sum = %d\n", sum(test, sizeof(test) / sizeof(test[0]));
}


回答4:

Arrays are always passed by reference in C, you can't change that.

What you can do is make a copy of array and pass the new array in the function



回答5:

As the others noted, the only way in C to pass an array by value is to use a struct with a fixed size array. But this is not a good idea, because the array size will be hardcoded into the struct definition.

However, you really should not try to pass arrays by value. Instead, what you should do is simply to declare your pointer parameter as const, like this:

int sum(size_t count, const int* array) {

While this does not pass the array by value, it clarifies the intent not to change the array, i. e. you can now treat sum() as if you were passing the array by value.
If your function does indeed not change the array (like your sum() function), using a const pointer comes for free, copying the array to pass it by value would just waste time.
If your function really wants to change a private copy, do so explicitely within the function. If the array won't get too large, you can simply allocate it on the stack, like so:

int doSomethingWithPrivateCopy(size_t count, const int* array) {
    int mutableCopy[count];
    memcpy(mutableCopy, array, sizeof(mutableCopy));
    //Now do anything you like with the data in mutable copy.
}