Перегрузка функции в C - PullRequest
21 голосов
/ 21 апреля 2010

Сегодня, глядя на справочную страницу для open(), я заметил, что эта функция «перегружена»:

   int open(const char *pathname, int flags);
   int open(const char *pathname, int flags, mode_t mode);

Я не думал, что это возможно на C. Каков трюк для достижения этого?

ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ:
Так что на самом деле это не перегрузка, потому что при использовании varargs - вы можете указать только несколько аргументов одного типа. Итак, mode_t за кадром - int?

Ответы [ 5 ]

32 голосов
/ 21 апреля 2010

Используется переменные аргументы . Эти объявления появляются только на странице руководства, так как эти 2 - единственный способ, которым вы должны вызывать open (). Фактическая функция C будет объявлена ​​как, например,

int open(const char *pathname,int flags,...);

С переменными аргументами аргументы не обязательно должны быть одного типа. printf является очевидным примером этого.

В случае open () первый аргумент переменной должен быть mode_t, если 'flags содержит флаг O_CREAT, потому что реализация open () ожидает, что он будет mode_t (который за кулисами, вероятно, является неподписанным int или долго без знака - но это не имеет ничего общего с varargs)

10 голосов
/ 21 апреля 2010

C позволяет написать функцию с переменным номером аргумента , таким как printf.

С учетом вышесказанного, нет надежного кроссплатформенного способав C написать функцию, которая принимает ровно 2 или 3 аргумента;в общем случае вы должны сделать что-то вроде

some_function(5, 6, 7, NULL);
some_function(5, 6, 8, 2, 5, NULL);

Другими словами, у вас должен быть завершающий аргумент "sentinal".В качестве альтернативы, вы могли бы как-то включить число параметров в более ранний параметр, такой как

another_func(2, "hello", "world");
another_func(3, "goodbye", "cruel", "world");

Семейство функций printf использует этот подход;первый параметр формата содержит количество необходимых дополнительных параметров;например, с printf("%f %f", 5.6, 7.11) вы знаете, что должно быть 2 параметра с плавающей точкой.Тем не менее, это было бы несколько небезопасно в пользовательской библиотечной функции, так как если бы вы сказали my_printf("%s %f %f %f %s", 5.6), то вы могли бы получить segfaults или еще хуже.К счастью, большинство компиляторов Си проверяют ваши вызовы 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
6 голосов
/ 21 апреля 2010

"режим должен быть указан, когда O_CREAT находится в флагах, и игнорируется в противном случае."

extern int open (__const char *__file, int __oflag, ...)

Используется varargs и загружается только аргумент переменной режима, если __oflag содержит O_CREAT.

3 голосов
/ 21 апреля 2010

очень короткий ответ - varargs

2 голосов
/ 21 апреля 2010

вы можете подделать его, используя список переменных аргументов с ...

int function(int x, ...);
...