c variables language-lawyer definition

¿Cuál es la razón detrás de las definiciones tentativas en C?



variables language-lawyer (2)

Aquí hay un ejemplo de un caso donde es útil:

void (*a)(); void bar(); void foo() { a = bar; } static void (*a)() = foo; /* ... code that uses a ... */

El punto clave es que la definición de foo tiene que referirse a a , y la definición de a tiene que referirse a foo . También deberían ser posibles ejemplos similares con estructuras inicializadas.

Considere el siguiente programa. ¿Dará esto algún error de compilación?

#include <stdio.h> int s=5; int s; int main(void) { printf("%d",s); }

A primera vista, parece que el compilador dará un error de redefinición variable, pero el programa es perfectamente válido de acuerdo con el estándar C. (Ver demostración en vivo aquí http://ideone.com/Xyo5SY ).

Una definición tentativa es cualquier declaración de datos externos que no tenga un especificador de clase de almacenamiento ni un inicializador.

C99 6.9.2 / 2

Una declaración de un identi fi cador para un objeto que tiene un alcance de archivo sin un inicializador, y sin un especi fi cador de clase de almacenamiento o con el especi fi cador estático de clase de almacenamiento, constituye una definición tentativa. Si una unidad de traducción contiene una o más definiciones provisionales para un identi fi cador, y la unidad de traducción no contiene una definición externa para ese identi fi cador, entonces el comportamiento es exactamente como si la unidad de traducción contuviera una declaración de alcance de archivo de ese identi fi cador, con el tipo compuesto como del final de la unidad de traducción, con un inicializador igual a 0.

Mi pregunta es, ¿cuál es la razón para permitir definiciones provisionales? ¿Hay algún uso de esto en C? ¿Por qué C permite definiciones tentativas?


Las definiciones provisionales se crearon como una manera de salvar modelos incompatibles que existían antes del C89. Esto se trata en la sección de fundamentos de C99 6.9.2 Definiciones de objetos externos que dice:

Antes de C90, las implementaciones variaban ampliamente con respecto a los identificadores de referencia directa con enlace interno (ver §6.2.2). El comité C89 inventó el concepto de definición tentativa para manejar esta situación. Una definición tentativa es una declaración que puede o no actuar como una definición: si una definición real se encuentra más adelante en la unidad de traducción, entonces la definición tentativa simplemente actúa como una declaración. Si no es así, entonces la definición tentativa actúa como una definición real. En aras de la coherencia, las mismas reglas se aplican a los identificadores con enlaces externos, aunque no son estrictamente necesarios.

y la sección 6.2.2 de la justificación C99 dice:

El modelo de definición que se usará para los objetos con enlace externo fue un problema importante de estandarización de C89. El problema básico fue decidir qué declaraciones de un objeto definen el almacenamiento para el objeto y cuáles simplemente hacen referencia a un objeto existente. Un problema relacionado fue si se permiten varias definiciones de almacenamiento o solo una es aceptable. Las implementaciones anteriores a C89 exhiben al menos cuatro modelos diferentes , que se enumeran aquí en orden de restricción creciente: