Pregunta

Aparentemente (al menos según gcc -std=c99) C99 no soporta la sobrecarga de funciones. La razón para no apoyar una nueva característica de C es por lo general la compatibilidad hacia atrás, pero en este caso no puedo pensar en un solo caso en el que la sobrecarga de funciones rompería la compatibilidad hacia atrás. ¿Cuál es el razonamiento detrás de no incluir esta característica básica?

¿Fue útil?

Solución

Para entender por qué no es probable que vea una sobrecarga en C, que podría ayudar a conocer mejor cómo se maneja la sobrecarga de C ++.

Después de compilar el código, pero antes de estar listo para funcionar, el intermedio código objeto deben ir unidos. Esto transforma una base de datos en bruto de funciones compiladas y otros objetos en una lista para cargar el archivo binario / marcha. Este paso adicional es importante porque es el mecanismo principio de modularidad a disposición de los programas compilados. Este paso le permite tomar código de bibliotecas existentes y se mezcla con su propia lógica de la aplicación.

En esta etapa, el código objeto puede haber sido escrito en cualquier lenguaje, con cualquier combinación de características. Para que esto sea posible, es necesario tener algún tipo de convención para que el enlazador es capaz de recoger el objeto correcto cuando otro objeto se refiere a ella. Si está de codificación en lenguaje ensamblador, cuando se define una etiqueta, ésta se utiliza exactamente, porque se supone que sabe lo que está haciendo.

En C, las funciones se convierten en los nombres de símbolos para el enlazador, por lo que cuando se escribe

int main(int argc, char **argv) { return 1; }

el compilador proporciona un archivo de código objeto, que contiene un objeto llamado main.

Esto funciona bien, pero significa que no se puede tener dos objetos con el mismo nombre, ya que el enlazador no sería capaz de decidir qué nombre se debe utilizar. El enlazador no sabe nada acerca de los tipos de argumentos, y muy poco de código en general.

C ++ resuelve este mediante la codificación de información adicional en el nombre de símbolo directamente. El tipo de retorno y el número y tipo de argumentos se añaden al nombre de símbolo, y se denominan así en el punto de una llamada de función. El enlazador no tiene que saber esto está sucediendo, incluso, ya que por lo que se puede decir, la llamada de función no es ambigua.

La desventaja de esto es que los nombres de los símbolos no se parecen en nada a los nombres de las funciones originales. En particular, es casi imposible predecir cuál es el nombre de una función sobrecargada será para que pueda enlazar con él. Para enlazar a Foriegn código, puede utilizar extern "C", lo que hace que esas funciones a seguir el estilo C de nombres de símbolos, pero por supuesto no se puede sobrecargar tal función.

Estas diferencias están relacionadas con los objetivos de diseño de cada idioma. C está orientada hacia la portabilidad y la interoperabilidad. C se sale de su manera de hacer las cosas predecibles y compatibles. C ++ está orientada más fuertemente hacia la construcción de sistemas ricos y poderosos, y no se centró terriblemente en la interacción con otros idiomas.

Creo que es poco probable que alguna vez C para perseguir cualquier característica que produciría código que es tan difícil para interactuar con como C ++.

Editar Imagist pregunta:

  

¿Sería realmente portátil o menos   más difíciles de interactuar con una   función si resuelto int main (int   argc, char ** argv) a algo como   main-int-int-char ** en lugar de a principal   (Y esto fuera parte de la norma)?   No veo un problema aquí. De hecho,   me parece que esto le da   más información (que podría ser utilizado   para la optimización y similares)

Para responder a esto, haré volver a C ++ y la forma en que se ocupa de las sobrecargas. C ++ utiliza este mecanismo, casi exactamente como se describe, pero con una advertencia. C ++ no estandariza cómo se deben implementar ciertas partes de sí mismo, y luego pasa a sugerir cómo algunas de las consecuencias de esa omisión. En particular, C ++ tiene un sistema de tipo rico, que incluye miembros de la clase virtuales. Como esta función debe implementarse se deja a los autores de compiladores, y los detalles de la resolución vtable tiene un fuerte efecto sobre las firmas de función. Por esta razón, C ++ sugiere deliberadamente hacen los autores de compiladores nombre mangling ser incompatibles entre sí a través de compilers o compiladores mismos con diferentes implementaciones de estas características clave.

Esto es sólo un síntoma de la cuestión más profunda que mientras lenguajes de alto nivel como C ++ y C tienen sistemas de tipo detalladas, el código máquina de nivel inferior es totalmente sin tipo. arbitrariamente sistemas de tipos ricos se construyen en la parte superior del binario sin tipo proporcionado a pie de máquina. Enlazadores no tienen acceso a la información de tipo rica disponible para los lenguajes de alto nivel. El enlazador es completamente dependiente del compilador para manejar todas las abstracciones tipo y producir adecuadamente el tipo libre de código objeto.

C ++ hace esto mediante la codificación de toda la información de tipo necesario en los nombres de objeto destrozados. C, sin embargo, tiene un enfoque muy diferente, con el objetivo de ser una especie de lenguaje ensamblador portátil. C prefiere así tener una estricta a una correspondencia entre el nombre declarado y el nombre del símbolo objetos resultante. Si C Mangled es nombres, incluso en una forma estandarizada y predecible, que tendría que ir a grandes esfuerzos para que coincida con los nombres alterados a los nombres de los símbolos deseados, o de lo contrario tendría que apagarlo como lo hace en C ++. Este esfuerzo adicional se produce en casi ningún beneficio, porque a diferencia de C ++, sistema de tipos de C es bastante pequeño y sencillo.

Al mismo tiempo, es prácticamente una práctica estándar para definir varias funciones C con nombres similares que varían sólo por los tipos que toman como argumentos. para un largo ejemplo de esto simplemente, echar un vistazo a la OpenGL espacio de nombres.

Otros consejos

Cuando se compila una fuente de C, los nombres de símbolos permanecerán intactos. Si se introduce la sobrecarga de funciones, debe proporcionar un nombre mangling técnica para evitar conflictos de nombres. En consecuencia, como C ++, se le han generado máquina de nombres de símbolos en el binario compilado.

Además, C no dispone de tipos de datos estrictos. Muchas cosas son convertir implícitamente el uno al otro en C. La complejidad de las reglas de resolución de sobrecarga podría introducir confusión en este tipo de lenguaje.

Muchos de los diseñadores del lenguaje, incluido yo, piensan que la combinación de sobrecarga de funciones implícitas con promociones de C puede resultar en código que es atrozmente difícil de entender. Como prueba, mirar el cuerpo de conocimiento acumulado sobre C ++.

En general, C99 tenía la intención de ser una modesta revisión en gran medida compatible con la práctica existente. La sobrecarga habría sido bastante grande de salida.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top