¿La función principal puede acceder a la función debajo de ella pero no a la variable?

Considere el siguiente código:

main() { func(); i = 8; } int i; func() { } 

Cómo mi función principal puede ver y llamar a func () pero no puede usar i, que también se define a continuación principal.

Respuesta rápida: No hagas eso. Todas las funciones y variables deben declararse explícitamente antes de su uso. Las versiones anteriores de C le permiten salirse con las declaraciones implícitas, pero no debería aprovechar eso.

En C89 / C90 (a veces llamado “ANSI C”, pero eso no es estrictamente exacto), si llama a una función sin una statement visible, se crea una statement implícita, asumiendo que la función devuelve int y toma argumentos de los tipos (promovidos) que Pasado en la llamada. No hay tales declaraciones implícitas para los objetos.

Dependiendo de esta regla es una mala idea. Si la función realmente devuelve un tipo distinto de int , o si sus parámetros no coinciden con los argumentos pasados ​​en la llamada, el comportamiento no está definido, y el comstackdor no está obligado a decirle que ha cometido un error.

Todas las funciones llamadas deben tener una statement explícita antes de ser llamadas y esa statement debe ser un prototipo , especificando los tipos de los parámetros.

El estándar ISO C de 1999 eliminó la regla ” int implícita”, por lo que es ilegal (una violación de restricción) llamar a una función sin una statement visible. (Lamentablemente, no es obligatorio que la statement sea un prototipo, pero siempre debe usar prototipos de todos modos). Muchos comstackdores todavía permiten llamadas usando las reglas anteriores. Debería averiguar cómo hacer que su comstackdor avise al menos sobre dichas llamadas.

Aquí hay una versión corregida de su progtwig, válida en C89 / C90, C99 y C11:

 void func(void); int i; int main(void) { func(); i = 8; } void func(void) { } 

O simplemente puede mover la definición de func encima de la definición de main (las “declaraciones de reenvío” generalmente no son necesarias a menos que tenga llamadas recursivas):

 void func(void); int i; int main(void) { func(); i = 8; } void func(void) { } 

En C, al llamar a una función no declarada se activan algunas reglas para componer los tipos del valor de retorno y los argumentos. Esta es una idea terrible, y siempre debe habilitar las advertencias del comstackdor que detectan este error. Obtendrá una rotura al pasar o devolver un valor de punto flotante en lugar de un int, o al pasar un puntero más ancho que un int.

Aún mejor, tenga su comstackdor en modo C99 o posterior, no en C89. La statement implícita se eliminó en C99, por lo que necesita al menos un prototipo.

No hay tales reglas para usar variables globales sin una statement en adelante.

En K&R C, las funciones se declaran implícitamente, devolviendo int y aceptando cualquier argumento cuando se usan sin ser declaradas.

Omitir el tipo de retorno también es por defecto int como tipo de retorno, por lo que la definición no entra en conflicto con la statement implícita.

Cuando el archivo de origen se analiza de arriba a abajo, el comstackdor debe ver la statement de todos los identificadores antes de su uso. La regla “int implícita” para funciones sin un tipo de retorno explícito es válida solo en C89 / 90. Se ha eliminado de la norma en C99. Así que la func() necesita un prototipo en C99 y posteriores. Si está comstackndo en el modo C89 / 90, entonces no hay ningún error para la función func() . GCC genera las siguientes advertencias en el modo C99 para su código (sin la statement i=8 ):

 $gcc -Wall -Wextra -std=c99 file.c warning: implicit declaration of function func warning: return type defaults to int 

No se realiza tal statement implícita implícita para la variable i incluso en C89 / 90. Una excepción son los parámetros de función.

Por ejemplo,

 int main(i) { func(); i = 8; } 

está bien porque por defecto escribo int en C89 / 90. Pero no es válido en C99 y posteriores.

Para que su progtwig sea válido en C moderno, debe ser:

 void func(); // (1) Prototype for func() int main(void) // (2) return type of main() should be int { func(); extern int i; // (3) refers to the `i` tentatively defined after main() i = 8; } int i; void func() { }