Поддерживает ли C перегрузку?


Я просто хочу знать, поддерживает ли C загрузку? Поскольку мы используем системные функции, такие как printf с разными аргументами no. Помоги мне

9 52

9 ответов:

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

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

printf("%d", 12); // int overload?
printf("%s", "hi"); // char* overload?

на самом деле это не так. Есть только одна функция printf, но компилятор использует специальный вызов конвенции это назвать, где все аргументы, которые вы предоставляете, последовательно помещаются в стек [*]. printf (или vprintf) проверяет строку формата и использует ее для определения способа чтения этих аргументов обратно. Вот почему printf не является типобезопасным:

char *format = "%d";
printf(format, "hi"); // undefined behaviour, no diagnostic required.

[*] стандарт на самом деле не сказать они передаются в стек или вообще упоминают стек, но это естественная реализация.

C не поддерживает перегрузку. (Очевидно, даже если бы это было так, они не использовали бы это для printf: вам понадобится printf для каждой возможной комбинации типов!)

функции printf использует varargs.

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

все зависит от того, как вы определяете "поддержка".

очевидно, что язык C предоставляет перегруженные операторы в основном языке, так как большинство операторов в C имеют перегруженную функциональность: вы можете использовать binary + с int,long и с типами указателей.

но в то же время C не позволяет вам создавать свои собственные перегруженные функции, а стандартная библиотека C также должна прибегать к различным именам функций, которые будут использоваться с различные типы (например abs,fabs,labs и так далее).

нет, C не поддерживает перегрузку. Если вы хотите реализовать перегрузку, подобную C++, вам придется вручную исказить имена функций, используя какое-то согласованное соглашение. Например:

int myModule_myFunction_add();
int myModule_myFunction_add_int(int);
int myModule_myFunction_add_char_int(char, int);
int myModule_myFunction_add_pMyStruct_int(MyStruct*, int);

не напрямую, и это не как printf работает, но можно создать эквивалент перегруженных функций с помощью макросов, если типы имеют разные размеры. Тип-общие математические функции в tgmath.h стандарт C99 может быть реализован таким образом.

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

void foo(int);
int foo(char*);
long foo(char *, char **);

компиляция в функции с именем что-то вроде v__foo_i, i__foo_pc и l__foo_pc_ppc [компиляторы используют разные соглашения об именах, хотя стандарт C++ запрещает использование внутренних двойных подчеркиваний в идентификаторы, чтобы компиляторы могли давать имена вещей, как указано выше, без конфликтов]. Авторы стандарта C не хотели требовать от компиляторов изменения соглашений об именах для обеспечения перегрузки, поэтому они не предусматривают этого.

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

void foo_zz1(int);
int foo_zz2(char*);
long foo_zz3(char *, char **);
inline void foo(int x) { foo_zz1(x); }
inline int foo(char* st) { foo_zz2(st); }
long foo(char *p1, char **p2) { foo_zz3(p1,p2); }

Я помню, как смотрел на встроенный компилятор для гибрида между C и C++, который поддерживал вышеизложенное как нестандартное расширение, но я не уверен в деталях. В любом случае, даже если некоторые компиляторы C поддерживают перегрузку функций, которые не имеют внешней связи, она не поддерживается C14 и я не знаю (к сожалению) о каких-либо активных усилиях по добавлению такой функции в будущие стандарты C.

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

#define nyb_swap(x) \
  ((((x) & 1)<<3) | (((x) & 2)<<1) | (((x) & 4)>>1) | ((((x) & 8)>>3) )
#define byte_swap(x) \
  ( (nyb_swap(x)<<4) | nyb_swap((x) >> 4) )
#define word_swap(x) \
  ( (byte_swap(x)<<24) | (byte_swap((x) >> 8)<<16) | \
    (byte_swap((x) >> 16)<<8) | (byte_swap((x) >> 24)) )

и выражение типа uint32_t x=word_swap(0x12345678); просто нагрузка x С 0x87654321. С другой стороны, если значение не является константой, результат будет ужасным: выражение типа uint32_t y=word_swap(x); может генерировать много десятков инструкций; вызов функция с частично развернутым циклом будет почти такой же быстрой, но гораздо более компактной. С другой стороны, использование цикла не позволит рассматривать результат как константу времени компиляции.

используя GCC, можно определить макрос, который будет либо использовать постоянный макрос, если задана константа, либо вызывать функцию, когда задана переменная:

#define wswap(x) \
  (__builtin_constant_p((x)) ? word_swap((x)) : word_swap_func((x))

этот подход не может сделать все, что может сделать перегрузка на основе типов, но он может сделать много вещей перегрузки не могу.

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

No c не поддерживает перегрузку функций. Но вы можете получить его для компиляции / работы, если вы используете G++ (компилятор c++).