Подтвердить что ты не робот

Что означает... означает в списке аргументов в C?

Я столкнулся с следующей сигнатурой функции, и я задавался вопросом, является ли это (эллипсис или "...") своего рода полиморфизмом?

#include <fcntl.h>
int fcntl(int fd, int cmd, ... );

Спасибо заранее.

4b9b3361

Ответ 3

... означает, что вы можете передать любое количество аргументов этой функции, как уже отмечали другие комментаторы. Поскольку необязательные аргументы не печатаются, компилятор не может проверять типы, и вы можете технически передать любой аргумент любого типа.

Значит ли это, что вы можете использовать это для реализации какой-то полиморфной функции? (I.e., функция, выполняющая некоторую операцию, основанную на типе ее аргументов.)

Нет.

Причина, по которой вы не можете этого сделать, заключается в том, что во время выполнения вы не можете проверять типы переданных аргументов. Ожидается, что функция чтения в списке аргументов параметров уже знает типы необязательных аргументов, которые она собирается получить.

В случае функции, которая действительно должна иметь возможность принимать любое количество аргументов любого типа (т.е. printf), типы аргументов передаются через строку формата. Это означает, что вызывающий должен указать типы, которые он собирается передать при каждом вызове, удаляя преимущества полиморфных функций (что вызывающий не должен также знать типы).

Для сравнения:

// Ideal invocation
x = multiply(number_a, number_b)
y = multiply(matrix_a, matrix_b)

// Standard C invocation
x = multiply_number(number_a, number_b)
y = multiply_matrix(matrix_a, matrix_b)

// Simulated "polymorphism" with varargs
x = multiply(T_NUMBER, number_a, number_b)
y = multiply(T_MATRIX, matrix_a, matrix_b)

Вы должны указать тип перед тем, как функция varargs сможет сделать правильную вещь, так что это ничего не получает.

Ответ 4

Нет, что "эллипсис" вы видите там, предполагая, что вы ссылаетесь на часть объявления ....

В основном это говорит о том, что эта функция принимает неизвестное количество аргументов после первых двух, которые указаны там.

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

Для других функций, которые поддерживают это, посмотрите на функцию printf и ее варианты.

Ответ 5

Поддерживает ли C полиморфизм? Нет, нет.

Однако существует несколько библиотек, таких как API Python C, которые реализуют грубый вариант полиморфизма с использованием структур и указателей. Помните, что компилятор не может выполнять соответствующую проверку типов в большинстве случаев.

Простая процедура:

typedef struct {
    char * (*to_string)();
} Type;

#define OBJ_HEADER Type *ob_type

typedef struct {
    OBJ_HEADER;
}  Object; 

typedef struct {
    OBJ_HEADER;
    long ival;        
} Integer;

typedef struct {
    OBJ_HEADER;
    char *name;
    char *surname;
} Person;

Integer и Person получают объект Type с соответствующими указателями на функции (например, для функций типа integer_to_string и person_to_string).

Теперь просто объявите функцию, принимающую объект *:

void print(Object *obj) {
    printf("%s", obj->type->to_string());
}

теперь вы можете вызвать эту функцию как с Integer, так и с Person:

Integer *i = make_int(10);
print((Object *) i);

Person *p = make_person("dfa");
print((Object *) p);

ИЗМЕНИТЬ

альтернативно вы можете объявить я и p как Object *; конечно make_int, и make_person выделит пространство для Integer и Person и сделает соответствующий бросок:

Object * 
make_integer(long i) {
     Integer *ob = malloc(sizeof(Integer));
     ob->ob_type = &integer_type;
     ob->ival = i;
     return (Object *) ob;
}

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

Я столкнулся с следующей сигнатурой функции, и я задавался вопросом, является ли это (эллипсис или "..." ) своего рода полиморфизмом?

да, это примитивная форма полиморфизма. Имея только одну сигнатуру функции, вы можете передавать различные структуры. Однако компилятор не может помочь вам обнаружить ошибки типа.

Ответ 6

Добавление к сказанному: C поддерживает полиморфизм с помощью других средств. Например, возьмите стандартную библиотеку qsort, которая сортирует данные произвольного типа.

Он может сделать это с помощью нетипизированных указателей (void) к данным. Он также должен знать размер данных для сортировки (предоставляется через sizeof) и логику, которая сравнивает порядок объектов. Это достигается путем передачи указателя на функцию qsort.

Это яркий пример полиморфизма времени выполнения.

Существуют другие способы реализации объектно-ориентированного поведения (в частности, вызовов виртуальных функций) путем управления таблицами виртуальных функций вручную. Это можно сделать, сохранив указатели функций в структурах и передав их. Многие API делают это, например. WinAPI, который даже использует расширенные аспекты ориентации объекта, например. диспетчер отправки базового класса (DefWindowProc, чтобы имитировать вызов виртуального метода базового класса).

Ответ 7

Я предполагаю, что вы имеете в виду эллипсис (...)? Если это так, это означает, что последуют 0 или более параметров. Он называется varargs, определенный в stdarg.h

http://msdn.microsoft.com/en-us/library/kb57fad8.aspx

printf использует эту функцию. Без него вы не сможете добавлять параметры в конец функции.

Ответ 8

Объявление printf в стандартной библиотеке

int printf(const char*, ...); 

Подумайте об этом.

Ответ 9

C поддерживает грубую форму полиморфизма. То есть тип, который может появляться и вести себя как другой тип. Он работает аналогично тому, как на С++ под капотом (полагаясь на выровненную память), но вы должны помочь компилятору выполнить кастинг. Например. вы можете определить структуру:

typedef struct {
     char forename[20];
     char surname[20];
     } Person;

И затем другая структура:

    typedef struct {
             char forename[20];
             char surname[20];
             float salary;
             char managername[20];
             } Employee;

Тогда

int main (int argc, int *argv)
{
    Employee Ben;
    setpersonname((Person *) &Ben);
}

void setpersonname(Person *person)
{
   strcpy((*person).Name,"Ben");
}

В приведенном выше примере показано, что Employee используется как Person.

Ответ 10

Нет, это функция, которая принимает переменное количество аргументов.

Ответ 11

Это не технический полиморфизм. fcntl принимает переменное количество аргументов, и это является причиной... аналогично функции printf.

Ответ 12

C не поддерживает перегрузку функций - это тип ad-hoc-полиморфизма, основанный на типах времени компиляции, и не многократная диспетчеризация (т.е. перегрузка на основе типов времени выполнения).

Чтобы имитировать перегрузку функции на C, вам нужно создать несколько именованных функций. Имена функций часто содержат информацию типа, например fputc() для символов и fputs() для строк.

Многократная отправка может быть реализована с использованием переменных массивов. Опять же, это задание программиста для предоставления информации о типе, но на этот раз через дополнительный аргумент, который будет оцениваться во время выполнения - в отличие от имени функции времени компиляции в случае описанного выше подхода. Семейство функций printf() может быть не лучшим примером для множественной отправки, но я не могу сейчас думать об этом лучше.

Существуют другие подходы к многократной диспетчеризации с использованием указателей вместо переменных функций или обертывания значений в структурах для предоставления аннотаций типа.

Ответ 13

Вы можете написать код, который поддерживает Полиморфное поведение в C, но... (эллипсис) не будет большой помощью. Это для переменных аргументов функции.

Если вы хотите использовать полиморфное поведение, объединения и структуры для построения структуры данных, которая имеет раздел "тип" и переменные поля в зависимости от типа. Вы также можете включить таблицы указателей функций в структуры. Пуф! Вы изобрели С++.

Ответ 14

Да C Поддерживает полиморфизм

Код, который мы пишем в С++, используя виртуальный для реализации полиморфизма если сначала преобразовать в код C компилятором (здесь можно найти подробности здесь).

Хорошо известно, что виртуальная функциональность в С++ реализована с использованием указателей функций.