Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a C function that accepts parameters of different data types

Tags:

c

function

I'm relatively new to the C programming language, and I'm trying to figure out how to create a function that can accept different types of data as parameters. The function is supposed to count and return the number of elements in a character or integer array. I already have two separate functions that will do this, but I would really like to be able to use one function for both tasks. Is there a way to do this in C?

Thanks in advance!

like image 684
Sheldon Juncker Avatar asked Jul 16 '13 02:07

Sheldon Juncker


3 Answers

So, let's assume your two functions are called sizeof_char_array and sizeof_int_array.

In C11, there is a new feature called "generic selection" that will let you do what you want with a relatively simple macro:

#define sizeof_array(X) \
    _Generic (*(X), \
              char: sizeof_char_array, \
              default: sizeof_int_array) (X)

(I don't even have a C11 implementation to test this against, so caveat emptor!)

Prior to C11, this was sometimes accomplished with a macro using regularly named functions. You can define a macro that will call one function or the other depending on a macro argument hint:

#define sizeof_array(xtype, x) sizeof_ ## xtype ##_array(x)

int a[] = { 1, 2, 3, 4, -1 };
char b[] = "abc";

sizeof_array(int, a);   /* macro expands to sizeof_int_array(a) */
sizeof_array(char, b);  /* macro expands to sizeof_char_array(b) */

If the input argument is truly an array, you can use a macro to compute its size directly:

#define ARRAY_SZ(x) (sizeof(x)/((void *)x == &x ? sizeof(x[0]) : 0))

In the case of an array, the following expression is true:

(void *)arr == &arr

Because the address of an array has the same location in memory as the address of its first element.

So, the macro computes: sizeof(arr)/sizeof(arr[0]). Since the sizeof operator reports the size in bytes of its argument, the computed expression results in the number of elements in the array. However, if you are using a sentinel to compute the length, the ARRAY_SZ macro will result in a size at least one larger than the length found traversing the array for the sentinel.

In the case that the argument is not an array, then the expression results in a divide by 0 exception.

like image 165
jxh Avatar answered Oct 17 '22 18:10

jxh


The answer is quite simple. You do need a function for this task. Just try this piece of code

#define len(array) sizeof(array)/sizeof(*array)

and that's it.

Important note: As pointed out in the comments, this will not work for dynamically allocated arrays.

like image 37
lakshayg Avatar answered Oct 17 '22 19:10

lakshayg


You should make your function arguments take in a void * type. This way, you can pass in different types of data, and type-cast it to the one you want. However, you do need to watch out because there is no guaranteed way to correctly 'guess' the type that a void* points to.

like image 40
jh314 Avatar answered Oct 17 '22 19:10

jh314