Cami k
Cami k

Reputation: 11

Passing arguments of any type to function in C

I would like to ask if it is possible to use a "void" variable that works the same as the pointer void (where you can store a pointer to any type of data like int, char etc). For example, function(void variable) to which I can pass any variable, like function(4) or function("hi").
Thank you!
PD: I'm doing an exercise related to simple linked lists (through structs)

typedef struct _GNodo {
    void *dato;struct _GNodo *sig;
} GNodo;

GList GList_agregar_final(GList lista, void dato) {
  GNodo *nuevoNodo = malloc(sizeof(GNodo));
  nuevoNodo->dato = dato;
  nuevoNodo->sig = NULL;

  if (lista == NULL)
    return nuevoNodo;

  GList nodo = lista;
  for (;nodo->sig != NULL;nodo = nodo->sig);
  /* ahora 'nodo' apunta al ultimo elemento en la lista */

  nodo->sig = nuevoNodo;
  return lista;
}

Upvotes: 1

Views: 747

Answers (4)

Guy haimovitz
Guy haimovitz

Reputation: 1625

No, you can׳t because the compiler must know the argument size at compilation time, if you want to pass a generic object you should pass void * instead, this is fine because the size of a pointer is known at compilation time.

Upvotes: 2

This is not possible in standard C. Read e.g. n1570 or some newer standard. Since some implementations passes argument in CPU registers (a different register for int and double, for example Linux amd64 ABI) .

See also variadic functions with <stdarg.h> which requires at least one fixed argument

You could also pass a pointer to some union, or a union of pointers and other types. Of course, you need a documented convention to choose the union member. Read more about tagged unions. Study for inspiration the source code of GNU bash or of the sash shell. They are open source software.

BTW GList could be used in GTK (its Glib part). Study it carefully, it is a well written open source toolkit: download its source code and study it. It has some GVariant

Consider also using the Clang static analyzer, or Frama-C, or even Bismon (a static analyzer above GCC for embedded code written in C or C++) on your C source code. For Frama-C or Bismon contact me by email to [email protected]

If you use GCC to compile your C code, invoke it as gcc -Wall -Wextra -g then use the GDB debugger to understand the behavior of your program.

Upvotes: 2

0___________
0___________

Reputation: 67546

In your case, you can:

List GList_agregar_final(GList lista, const void *dato, size_t dataSize) {
  GNodo *nuevoNodo = malloc(sizeof(*nuevoNodo));
  /* check if allocation did not fail */
  nuevoNodo->dato = malloc(dataSize);
  /* check if allocation did not fail */
  memcpy(nuevoNodo -> dato, data, dataSize);
  nuevoNodo->sig = NULL;
  /* ... */
    GList_agregar_final(lista, (int[]){4}, sizeof((int[]){4}));
    GList_agregar_final(lista, "hi", sizeof("hi"));

Do not use types in the sizeof only objects as in my example

Upvotes: 0

mkayaalp
mkayaalp

Reputation: 2716

No, the compiler needs to know the size of a parameter. It works with a pointer since void * has a known size, but void does not.

Upvotes: 2

Related Questions