2010-02-28 17 views
50

Solo quiero saber si C soporta sobrecarga? Como usamos funciones del sistema como printf con diferentes no de argumentos. Ayúdame¿C soporta sobrecarga de C?

+2

Duplicado: http://stackoverflow.com/questions/479207/function-overloading-in-c –

+0

Consulte la respuesta de Leushenko en 2014 con C11 _Selector de tipo genérico en el dupe http://stackoverflow.com/questions/479207/function -overloading-in-c. –

Respuesta

44

n, C no admite ningún tipo de sobrecarga (a menos que contar el hecho de que los operadores internos están sobrecargados ya, a ser una forma de sobrecarga ).

printf funciona usando una característica llamada varargs. Usted hace una llamada que se ve que podría ser sobrecargado:

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

En realidad no lo es. Solo hay una función printf, pero el compilador utiliza una convención de llamada especial para llamarla, donde los argumentos que proporciones se colocan en secuencia en la pila [*]. printf (o vprintf) examina la cadena de formato y la usa para averiguar cómo volver a leer esos argumentos. Esta es la razón por printf no es de tipo seguro:

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

[*] la norma no hace realmente dicen que están pasan en la pila o una pila mencionan en absoluto, pero esa es la aplicación naturales .

+0

No puedo hablar de todos los compiladores, pero el que yo trabajo hace que la persona que llama ajusta la pila para los argumentos que empujó, una vez que la función retorna. Esto me parece una buena idea para las funciones variadas, más seguro que hacer que la función las saque de la pila. – tomlogic

+1

Tiene razón, en realidad la convención de llamadas cdecl funciona exactamente así (la persona que llama es responsable de la limpieza de la pila); Eliminé el comentario para evitar confundir a otros lectores. El verdadero problema es con scanf, que, si proporciona una cadena de formato incorrecta, puede escribir los datos en ubicaciones aleatorias (tomadas de la pila) en la memoria. –

+0

C1X soportará a través de expresiones genéricas tipo y macros – Spudd86

29

C no es compatible con la sobrecarga. (Obviamente, incluso si lo hiciera, no usarían eso para printf: ¡necesitaría una impresión para cada combinación posible de tipos!)

printf usa varargs.

0

C No es compatible con la sobrecarga. Pero podemos implementar esa funcionalidad programando nuestra propia biblioteca que a su vez podría proporcionar soporte de sobrecarga.

+2

No estoy seguro de lo que quiere decir. ¿Qué aspecto tendría una biblioteca que proporciona soporte de sobrecarga? – sepp2k

+1

@ sepp2k, un conjunto de tablas de punteros de función. –

+0

@Carl: Parece que estás hablando de un vtable. Eso es por herencia, no estoy seguro de cómo eso ayudaría con la sobrecarga. – sepp2k

5

No, C no admite sobrecarga. Si desea implementar una sobrecarga similar a C++, tendrá que modificar sus nombres de funciones manualmente, utilizando algún tipo de convención consistente. Por ejemplo:

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); 
8

Todo depende de cómo defina el "soporte".

Obviamente, lenguaje C proporciona operadores sobrecargados dentro del núcleo del lenguaje, ya que la mayoría de los operadores en C han sobrecargado funcionalidad: se puede usar binaria + con int, long y con tipos de puntero.

embargo, al mismo tiempo C no permite al usuario crear sus propias funciones sobrecargadas, y la biblioteca estándar de C también tiene que recurrir a funciones con nombres diferentes, para ser utilizado con diferentes tipos (como abs, fabs, labs y así sucesivamente)

En otras palabras, C tiene algún grado de sobrecarga codificado en el lenguaje central, pero ni la biblioteca estándar ni los usuarios pueden hacer su propia sobrecarga.

-5

No c no es compatible con la sobrecarga de funciones. Pero puede obtenerlo para compilar/trabajar si está usando g ++ (un compilador de C++).

+3

-1, si está escribiendo C debe usar un compilador C. –

+4

Secundado. Si está utilizando un compilador de C++ para compilar su código, lo que está escribiendo es código C++, no código C. ¡Especialmente si está usando características de C++ que no están en C, como la sobrecarga de funciones! –

+0

en serio -2 jaja – chinmaya

1

No directamente, y así no es como funciona printf, pero es posible crear el equivalente de funciones sobrecargadas usando macros si los tipos son de tamaños diferentes. Las funciones matemáticas genéricas de tipo en tgmath.h del estándar C99 pueden implementarse de esa manera.

1

No existe ninguna disposición en el estándar C para la sobrecarga del operador; las propuestas para agregarlo han sido rechazadas sobre la base de que muchos sistemas de compilación no tienen capacidad para acomodar múltiples funciones con el mismo nombre. Mientras que C++ puede solucionar esto, p. Ej. teniendo

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

compilar a funciones con nombre algo así como v__foo_i, i__foo_pc y l__foo_pc_ppc [compiladores utilizan diferentes convenciones de nombres, aunque el estándar de C++ prohíbe el uso de dobles guiones internos en los identificadores con el fin de permitir que los compiladores para dar nombres de las cosas como el anterior sin conflicto]. Los autores del estándar C no quisieron exigir a ningún compilador que cambiara las convenciones de nomenclatura para permitir la sobrecarga, por lo que no la proporcionaron.

Sería posible y útil para un compilador permitir la sobrecarga de funciones estáticas y en línea sin crear problemas de nomenclatura; esto sería en la práctica ser tan útil como lo que permite la sobrecarga de funciones externamente reticulables ya que uno podría tener un archivo de cabecera:

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); } 

Recuerdo mirar a un compilador integrado para un híbrido entre C y C++ que apoyó lo anterior como una extensión no estándar, pero no estoy seguro de los detalles. En cualquier caso, incluso si algunos compiladores de C soportan la sobrecarga de funciones que no tienen enlaces externos, no es compatible con C14 ni estoy consciente (desafortunadamente) de ningún esfuerzo activo para agregar tal característica a los futuros estándares de C.

Sin embargo, GCC se puede hacer, usando macros, para soportar una forma de sobrecarga que no se admite directamente en idiomas con sobrecarga del operador. GCC incluye un intrínseco que identificará si una expresión se puede evaluar como una constante de tiempo de compilación. Al usar esto intrínseco, uno puede escribir una macro que puede evaluar una expresión de diferentes maneras (incluso llamando funciones) dependiendo del argumento. Esto puede ser útil en algunos casos en que una fórmula se evaluaría como una constante de tiempo de compilación si se le diese un argumento constante en tiempo de compilación, pero arrojaría un desorden horrible si se le diera un argumento de variable. Como un simple ejemplo, supongamos que uno desea invertir un valor de 32 bits. Si el valor es constante, se podría hacer eso a través de:

#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))) 

Y una expresión como uint32_t x=word_swap(0x12345678); simplemente cargar x con 0x87654321. Por otro lado, si el valor no es una constante, el resultado sería horrible: una expresión como uint32_t y=word_swap(x); podría generar muchas docenas de instrucciones; una llamada a una función con un bucle parcialmente desenrollado sería casi igual de rápida pero mucho más compacta. Por otro lado, el uso de un bucle evitaría que el resultado sea considerado como una constante de tiempo de compilación.

con gcc, se puede definir una macro que, o bien utilizar la macro-rendimiento constante si se les da una constante, o llamar a una función cuando se le da una variable:

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

Este enfoque no puede hacer todo tipo de Sobrecargar puede bastar, pero puede hacer muchas cosas que no pueden sobrecargar.