Passing any array type to a function in C

时间:2016-04-21 22:07:32

标签: c arrays function

I am trying to write a function that makes ordenations over any numeric array given to it. The problem is that C needs to know the data type to iterate through the array properly, because of its "pointer nature". Is there any way that I can pass any array without knowing the type? Maybe using the void type?

void ordenation (void *array, ...) {}

3 个答案:

答案 0 :(得分:0)

Here's how I understand your question, please reply below if that's not it. You are trying to create a function in C that can accept arrays of multiple numeric types (float, int, etc.).

This is called function overloading. It is possible to do it in C11 via the _Generic operator. See function overloading in C

Another option would be to create functions with a different name, all with a different parameter list. So:

    void ordenation_i(int *array);
    void ordenation_f(float *array);

Another way would be using the void* type. That would mean that you can pass any pointer to it and it may not be what you are looking for. You will have to cast the void* back to a pointer to something else, like a float. If that operation fails, you may have problems.

    void ordenation(void *array){
      float* array_casted = (float*) array; 
      // Do stuff
    }

The problem in this code is now that the array can only be used as a float array.

Finally, you could also just use a C++ compiler. It should compile any C code and you get function overloading by default.

    void ordenation(int array[]){
      //do stuff
    }

    void ordenation(float array[]){
      //do stuff
    }

答案 1 :(得分:0)

You can absolutely safely pass a pointer to any object to a function like this using void *. The problem, as others have pointed out, is that you have to do something with that object once you're in that function, and you'll need to know the type to do that, so even if you don't need the type to pass a pointer to the array, you're going to need it in some fashion to get any actual work done.

You can do it with C11 generics, as another answer states, but another possibility is to pass not only a pointer to the array, but a pointer also to the code you want to execute on it, using a function pointer.

For instance, the following code will add two to each element of any numeric array (I've implemented it only for int, long and double, but it's trivial to implement for the remaining standard numeric types). The add_two() function itself never has any idea what type of array it's getting. But to achieve this, you have to also pass it a pointer to a function which does know:

#include <stdio.h>

void add_two(void * array, size_t sz, void (*add_func)(void *, size_t));
void add_two_int(void * array, size_t idx);
void add_two_long(void * array, size_t idx);
void add_two_double(void * array, size_t idx);

int main(void)
{
    int n[] = {1, 2, 3, 4, 5};
    add_two(n, 5, add_two_int);
    for ( size_t i = 0; i < 5; ++i ) {
        printf("%zu: %d\n", i, n[i]);
    }

    long l[] = {1L, 2L, 3L, 4L, 5L};
    add_two(l, 5, add_two_long);
    for ( size_t i = 0; i < 5; ++i ) {
        printf("%zu: %ld\n", i, l[i]);
    }

    double d[] = {1.0, 2.0, 3.0, 4.0, 5.0};
    add_two(d, 5, add_two_double);
    for ( size_t i = 0; i < 5; ++i ) {
        printf("%zu: %f\n", i, d[i]);
    }

    return 0;
}

void add_two(void * array, size_t sz, void (*add_func)(void *, size_t))
{
    for ( size_t i = 0; i < sz; ++i ) {
        add_func(array, i);
    }
}

void add_two_int(void * array, size_t idx)
{
    int * n = array;
    n[idx] += 2; 
}

void add_two_long(void * array, size_t idx)
{
    long * l = array;
    l[idx] += 2; 
}

void add_two_double(void * array, size_t idx)
{
    double * d = array;
    d[idx] += 2; 
}

with output:

paul@horus:~/src/sandbox$ ./genarray
0: 3
1: 4
2: 5
3: 6
4: 7
0: 3
1: 4
2: 5
3: 6
4: 7
0: 3.000000
1: 4.000000
2: 5.000000
3: 6.000000
4: 7.000000
paul@horus:~/src/sandbox$ 

Of course, in this simple example there's not much in the way of real benefit to writing the add_two() function compared to just writing add_two_int() and friends and using them directly. But in a more complex example where you wanted, say, to have something like add_two() in a library, then this is a way for you to be able to deal with arbitrary and new types without having to modify add_two() or rebuild and redeploy your library.

Also, I've named the function add_two(), but it obviously just performs whatever operation you supply to it on each element in turn. So you could write the function subtract_two_int(void * array, size_t idx), for instance, pass it to add_two(), and it'll actually subtract two from each element, despite the name.

答案 2 :(得分:-1)

You can make the function void ordenation (void *array) and pass arrays of arbitrary data types into the function as long as you cast the input array like this ordenation ((void*)array) when calling the function. You should probably add a second input to denote the datatype of the corresponding array if you want to be able to use the array in your function. (I'm assuming the point of this is because C does not allow for function overloading?)