Перегрузка функций в C
Сегодня, глядя на страницу руководства для open()
, я заметил, что эта функция "перегружена":
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
Я не думал, что это возможно на C. Какой "трюк" для достижения этого?
ПОСЛЕДНИЕ ИЗМЕНЕНИЯ:
Поэтому он не перегружает, потому что при использовании varargs вы можете предоставить только несколько аргументов одного типа. Итак, mode_t
за кулисами int?
Ответы
Ответ 1
Он использует переменные аргументы. Эти объявления появляются только на странице руководства, так как эти 2 являются единственными способами, которые вы должны вызвать open(). Фактическая функция C будет объявлена, например,
int open(const char *pathname,int flags,...);
С переменными аргументами аргументы не должны быть одного типа. printf
- очевидный пример этого.
В случае open() первый переменный аргумент должен быть mode_t, если 'flags
содержит флаг O_CREAT, потому что реализация open() ожидает, что он будет mode_t (который за кулисами, скорее всего, представляет собой unsigned int или unsigned long - но это не имеет ничего общего с varargs)
Ответ 2
C делает возможным запись функции с переменной числом аргументов, например printf
.
С учетом сказанного, нет надежного кросс-платформенного способа в C, чтобы написать функцию, которая принимает ровно 2 или 3 аргумента; в общем, вы должны сделать что-то вроде
some_function(5, 6, 7, NULL);
some_function(5, 6, 8, 2, 5, NULL);
Другими словами, у вас должен быть завершающий "отважный" аргумент. В качестве альтернативы вы можете указать количество параметров как-то в более раннем параметре, например
another_func(2, "hello", "world");
another_func(3, "goodbye", "cruel", "world");
Семейство функций printf
принимает такой подход; первый параметр формата содержит необходимое количество дополнительных параметров; например с printf("%f %f", 5.6, 7.11)
вы знаете, что должно быть 2 параметра float. Однако это будет несколько небезопасно в пользовательской библиотечной функции, так как если бы вы сказали my_printf("%s %f %f %f %s", 5.6)
, тогда вы могли бы получить segfaults или еще хуже. К счастью, большинство компиляторов C будут проверять ваши вызовы на printf
во время компиляции, чтобы избежать такой проблемы.
В случае open
функция объявляется как имеющая переменные аргументы, а третий параметр проверяется только при установке O_CREAT
. Так вот как он "безопасно" определяет, присутствует ли третий аргумент. Я положил "безопасно" в кавычки, потому что технически нет возможности открывать для себя во время выполнения, сколько параметров было фактически передано. Например, следующие вызовы будут компилироваться без каких-либо ошибок или предупреждений:
open("foo.txt", 5, "not an integer", 7); // extra and invalid parameters
open("bar.txt", O_CREAT); // third parameter is missing
Ответ 3
"должен указываться, когда O_CREAT находится во флагах и в противном случае игнорируется."
extern int open (__const char *__file, int __oflag, ...)
Он использует varargs
и загружает только аргумент переменной режима, если __oflag
содержит O_CREAT
.
Ответ 4
очень короткий ответ - varargs
Ответ 5
вы можете подделать его с помощью списка переменных аргументов с помощью ...
int function(int x, ...);