Обычно не очень хорошая идея писать функции, которые принимают любой аргумент. Как отмечено в комментариях, вы теряете проверку, обеспечиваемую компилятором.
Однако, есть некоторые случаи, когда вы можете рассмотреть это с помощью 'void *', которые (обычно) считаются приемлемыми:(1) функции varargs и (2) обратный вызов. Важно подчеркнуть, что лучше по возможности рассмотреть альтернативную реализацию.
Функции varargs - это такие функции, как 'printf', 'scanf' и т. Д., Где функция может принимать переменное число аргументов, потенциально разных типов. и обычно использует ключи (или соглашения) из первых аргументов для правильного декодирования оставшихся аргументов.
Обратный вызов - это другой пример, где в коде иногда требуется указывать функцию, которая будет вызываться при событии. Многие фреймворки требуют, чтобы обратный вызов совпадал с предопределенным «typedef», где код позже приведёт аргументы к фактическому типу. Например, прототипу «qsort» требуется функция «сравнения», которая в общем случае определяется как «void *», где фактическая функция преобразует параметры в фактический тип.
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
В историческомОбратите внимание, что первоначальные версии «C» (иногда называемые «K & R C») позволяли определять функции без формального списка параметров. Практический опыт доказал, что это рискованно, непродуктивно. В те дни вы могли написать функцию в заголовочных файлах как:
/* in file.h */
int foo() ;
/* in file.c */
int foo(a)
int a ;
{
}
/* in prog.c */
{
a(5,4,"x") ;
}