Pregunta

Considere el programa C consta de dos archivos,

f1.c:

int x;

f2.c:

int x=2;

Mi lectura del párrafo 6.9.2 de el C99 estándar es que este programa debe ser rechazada. En mi interpretación de 6.9.2, x variable se define tentativamente en f1.c, pero esta definición provisional se convierte en una definición real al final de la unidad de traducción, y (en mi opinión), por lo tanto, debe comportarse como si f1.c contenía el int x=0; definición.

Con todos los compiladores (y, sobre todo, enlazadores) que fue capaz de tratar, esto no es lo que sucede. Todas las plataformas de compilación que intentaron hacer vincular los dos archivos anteriores, y el valor de x es 2 en ambos archivos.

Dudo que esto sucede por accidente, o simplemente como una característica "fácil" para proporcionar, además de lo que exige la norma. Si se piensa en ello, esto significa que hay un apoyo especial en el enlazador para aquellas variables globales que no tienen un inicializador, en contraposición a los inicializado explícitamente a cero. Alguien me dijo que la característica de engarce puede ser necesario para compilar Fortran de todos modos. Eso sería una explicación razonable.

¿Qué te parace esto? Otras interpretaciones de la norma? Los nombres de los archivos de plataformas en las que f1.c y f2.c se niegan a ser unidos entre sí?

Nota: esto es importante porque la cuestión se produce en el contexto del análisis estático. Si los dos archivos pueden negarse a estar vinculado en alguna plataforma, el analizador debe quejarse, pero si todas las plataformas de recopilación lo acepta, entonces no hay razón para advertir al respecto.

¿Fue útil?

Solución

¿Cuáles son las variables extern en C . Esto se menciona en la norma C en el anexo informativo J como una extensión común:

  

J.5.11 múltiples definiciones externas

     

Puede haber más de una definición externa para el identificador de un objeto, con o sin el uso explícito de la palabra clave extern; Si las definiciones no están de acuerdo, o más de uno se inicializa, el comportamiento es indefinido (6.9.2).

Advertencia

Como @litb señala aquí, y como se dice en mi respuesta a la pregunta de referencia cruzada, utilizando múltiples definiciones para una variable global conduce a un comportamiento indefinido, que es la forma de la norma de decir "cualquier cosa puede pasar". Una de las cosas que pueden suceder es que el programa se comporta como se esperaba; y J.5.11 dice, aproximadamente, "es posible que la suerte más a menudo de lo que merece". Sin embargo, un programa que se basa en múltiples definiciones de una variable extern - con o sin la palabra clave explícita 'extern' - no es un programa estrictamente conforme y no se garantiza que funcione en todas partes. De manera equivalente:. Que contiene un error , que pueden o no manifestarse

Otros consejos

Hay algo que se llama una "extensión común" a la norma, donde se permite siempre que la variable se inicializa las variables que definen una sola vez varias veces. Ver http://c-faq.com/decl/decldef.html

La página vinculada dice que esto es pertinente para las plataformas Unix - supongo que es el mismo para c99 c89 como - aunque quizás ha sido adoptado por más compiladores para formar una especie de estándar de facto. Interesante.

Esto es para aclarar mi respuesta a un comentario de olovb:

salida de nm para un archivo de objeto compilado de "int x;". En esta plataforma, los símbolos se precedidas por un '_', es decir, la variable x aparece como _x.

00000000 T _main
         U _unknown
00000004 C _x
         U dyld_stub_binding_helper

salida de nm para un archivo de objeto compilado de "int x = 1;"

00000000 T _main
         U _unknown
000000a0 D _x
         U dyld_stub_binding_helper

salida de nm para un archivo de objeto compilado de "int x = 0;"

00000000 T _main
         U _unknown
000000a0 D _x
         U dyld_stub_binding_helper

salida de nm para un archivo de objeto compilado de "int extern x;"

00000000 T _main
         U _unknown
         U dyld_stub_binding_helper

EDIT: salida nm para un archivo de objeto compilado de "extern int x;" donde x se utiliza realmente en una de las funciones

00000000 T _main
         U _unknown
         U _x
         U dyld_stub_binding_helper
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top