¿Cómo se nos permite usar un objeto o función declarada hacia adelante y cómo no?

Si declaramos un objeto o función sin definirlo, ¿cómo podemos usarlo antes de su statement y cómo no podemos usarlo antes de su statement? (Para una pregunta similar que utiliza una etiqueta de estructura declarada reenviada antes de su definición, básicamente cómo podemos usar un tipo incompleto y cómo no, consulte https://stackoverflow.com/a/45725061/3284469 )

¿Importa si la statement aparece en el scope del archivo o en el scope del bloque?

¿Importa si su definición aparece en la misma unidad de traducción o en una diferente?

Por ejemplo

extern int i; (what can we do with i here?) (what can't we do with i here?) int A = i+3; // error: initializer element is not constant. This is an error not due to forward declaration of int i int i = 3; void fun(); (what can we do with fun here?) (what can't we do with fun here?) void fun(){}; 

Declarar un objeto es una promesa de proporcionar una definición en otro lugar. Una vez que declara una función o una variable externa, a partir de ese momento se le permite hacer todo lo que se le permitiría hacer a una función o una variable que haya definido.

El scope de la statement no tiene efecto en lo que puede hacer, solo en la ubicación en el código donde puede hacerlo.

En la mayoría de los casos, el traductor de códigos requiere que se cumplan todas las referencias externas en el momento en que se vincula el código. De lo contrario, obtendrá un error de vinculación.

Una excepción a esta regla es usar el objeto declarado en una expresión sizeof , que no requiere acceso al objeto subyacente:

 extern int undefined; size_t res = sizeof(undefined); 

Lo anterior no romperá un enlace, porque sizeof expression no genera acceso a sus argumentos.

Puede hacer cualquier cosa con la statement, excepto para inscribirla. Por ejemplo:

 void fun(); inline void fun(){} 

Después de la statement, puede llamar a la función, a menos que la definición esté marcada en inline en cuyo caso se producirá un error de vinculador porque la definición no emite un símbolo para vincular. Incluso si no dice explícitamente en inline , un comstackdor de optimización puede en línea llamar a la función si se ha visto la definición.

http://www.cprogramming.com dice:

Cuando declara una variable, una función o incluso una clase, todo lo que está haciendo es decir: hay algo con este nombre y tiene este tipo. El comstackdor puede manejar la mayoría de los usos (pero no todos) de ese nombre sin necesidad de la definición completa de ese nombre. Declarar un valor, sin definirlo, le permite escribir código que el comstackdor puede entender sin tener que poner todos los detalles. Esto es particularmente útil si está trabajando con múltiples archivos fuente y necesita usar una función en varios archivos. No desea poner el cuerpo de la función en varios archivos, pero sí debe proporcionar una statement para ello.

 extern int i; 

Aquí, se ha declarado una variable de tipo entero i (pero ninguna definición, es decir, no hay asignación de memoria para la variable i hasta ahora). Y podemos hacer esta statement tantas veces como sea necesario.

 void fun(); 

Función fun() declara, pero no se define. pero le dice al comstackdor que puede usar esta función y espera que se defina en algún lugar.

que podemos hacer con yo aqui

Con

 extern int i; 
  1. Puedo ser declarado tantas veces como sea requerido en el progtwig.
  2. Puedes tener un inicializador

     extern int i = 0; 

¿Qué no podemos hacer con yo aquí?

No puedes usar i sin definirlo en el progtwig.

 extern int i; int main(void) { i = 10; // Will through an error return 0; } 

En el caso de la función, esta palabra clave solo indica que la vinculación de la función es extern . Por defecto, la vinculación de una statement de función / definición es externa.