2010-04-13 13 views
30

He estado trabajando en C durante tanto tiempo que el hecho de que los compiladores normalmente agreguen un guión bajo al comienzo de extern se entiende ... Sin embargo, another SO question today me hizo preguntarme sobre la verdadera razón por la cual se agrega el subrayado. A afirmaciones de que una razón es:¿Por qué los compiladores de C anteponen los guiones bajos a los nombres externos?

era una práctica común que los compiladores de C para anteponer un subrayado inicial a todos los identificadores de programa alcance externos para evitar enfrentamientos con las contribuciones de apoyo en el idioma de tiempo de ejecución

Creo que hay al menos un grano de verdad a esto, pero también parece que no responde realmente la pregunta, ya que si el guión bajo se agrega a todos los externos, no ayudará mucho a prevenir los enfrentamientos.

¿Alguien tiene buena información sobre la justificación del subrayado inicial?

¿Es el subrayado agregado parte del motivo por el que la llamada al sistema Unix creat() no termina con una 'e'? He oído que los primeros enlazadores en algunas plataformas tenían un límite de 6 caracteres para los nombres. Si ese es el caso, anteponer un guión bajo a los nombres externos parecería una idea muy loca (ahora solo tengo 5 personajes para jugar ...).

+2

Debe tenerse en cuenta que este comportamiento no se practica en los sistemas modernos de ELF. Era común en las plataformas aout/coff, aparentemente. –

+0

¿Por qué Clang lo hace en OS X? ¿Cómo puedo cerrarlo? – MarcusJ

Respuesta

17

era una práctica común que los compiladores de C para anteponer un subrayado inicial a todos los identificadores de programa alcance externos para evitar choques con las contribuciones de apoyo en el idioma de tiempo de ejecución

Si el soporte de ejecución es proporcionada por el compilador, se ¡pensaría que tendría más sentido anteponer un guión bajo a los pocos identificadores externos en el soporte de tiempo de ejecución en su lugar!

Cuando los compiladores C aparecieron por primera vez, la alternativa básica a la programación en C en esas plataformas era la programación en lenguaje ensamblador, y era (y de vez en cuando sigue siendo) útil vincular archivos de objetos escritos en ensamblador y C. Entonces realmente En mi humilde opinión, el subrayado principal añadido a los identificadores C externos era para evitar choques con los identificadores en su propio código de ensamblaje.

(Ver también GCC's asm label extension, y cuenta que esta subrayado antepuesto puede considerarse una forma simple de nombre mangling idiomas más complicados como C++ usar el nombre más complicado mangling, pero aquí es donde empezó..)

+0

Me gusta el sarcasmo "GCC aún no tiene la capacidad de almacenar variables estáticas en los registros. Quizás eso se agregará". comentar en el documento vinculado. –

+0

@MichaelBurr: posiblemente no es sarcástico. En algunos sistemas, puede reservar un registro global como un puntero a algún área de memoria (por ejemplo, 'R9' en algunas variaciones de ARM EABI para el puntero base estático). –

3

Por lo que siempre he escuchado es para evitar conflictos de nombres. No para otras variables externas, sino para que cuando utilice una biblioteca no entre en conflicto con los nombres de las variables de código de usuario.

1

De Wikipedia:

Era una práctica común que los compiladores de C para anteponer un subrayado inicial a todos los identificadores de programas externos alcance para evitar choques con las contribuciones de apoyo en el idioma en tiempo de ejecución. Además, cuando el compilador C/C++ necesitaba introducir nombres en el enlace externo como parte del proceso de traducción, estos nombres a menudo se distinguían con una combinación de varios guiones bajos iniciales o finales.

Esta práctica se codificó más tarde como parte de los estándares de lenguaje C y C++, en los que el uso de guiones bajos principales se reservó para la implementación.
3

La función principal no es el punto de entrada real de un archivo ejecutable. Algunos archivos vinculados estáticamente tienen el punto de entrada real que finalmente llama a main, y los archivos vinculados estáticamente poseen el espacio de nombres que no comienza con un guión bajo. En mi sistema, en/usr/lib, hay gcrt1.o, crt1.o y dylib1.o entre otros. Cada uno de ellos tiene una función de "inicio" sin un guión bajo que eventualmente llamará al punto de entrada "_main". Todo lo demás además de esos archivos tiene un alcance externo. La historia tiene que ver con mezclar assembler y C en un proyecto, donde todo C se considera externo.

5

si el compilador c siempre precedió un guión bajo antes de cada símbolo, , entonces el código de inicio/c-runtime (que generalmente está escrito en ensamblaje) puede usar etiquetas y símbolos que no comienzan con un guión bajo (como el símbolo ' comienzo').

incluso si escribe una función start() en el código c, se genera como _start en la salida del objeto/asm. (Tenga en cuenta que en este caso, no hay posibilidad de que el código c genere un símbolo que no comience con un guión bajo), por lo que el codificador no tiene que preocuparse por inventar símbolos oscuros improbables (como $ _dontuse42% $) para cada uno de sus variables/etiquetas globales.

por lo que el enlazador no se quejará de un choque de nombre, y el programador está contento. :)

lo siguiente es diferente de la práctica del compilador anteponiendo un subrayado en sus formatos de salida.

Esta práctica se codificó más tarde como parte de los estándares de lenguaje C y C++, en los que el uso de guiones bajos principales se reservó para la implementación.

que es una convención seguida, para las bibliotecas de c sytem y otros componentes del sistema. (y para cosas como __FILE__, etc.)

(tenga en cuenta que tal símbolo (por ejemplo: _Hora) puede dar lugar a 2 subrayado iniciales (__Hora) en la salida generada)

Cuestiones relacionadas