valores una todas tipos retornan que llamar lenguaje las funciones funcion ejemplos como c syntax standards

una - tipos de funciones en lenguaje c



Efectos de la palabra clave extern sobre las funciones C (8)

Debe distinguir entre dos conceptos separados: definición de función y declaración de símbolo. "extern" es un modificador de enlace, una sugerencia para el compilador acerca de dónde se define el símbolo al que se hace referencia después (la sugerencia es "no aquí").

Si escribo

extern int i;

en el alcance del archivo (fuera de un bloque de funciones) en un archivo C, entonces está diciendo "la variable puede definirse en otro lugar".

extern int f() {return 0;}

es tanto una declaración de la función f como una definición de la función f. La definición en este caso prevalece sobre la externa.

extern int f(); int f() {return 0;}

primero es una declaración, seguida de la definición.

El uso de extern es incorrecto si quiere declarar y definir simultáneamente una variable de alcance de archivo. Por ejemplo,

extern int i = 4;

dará un error o advertencia, según el compilador.

El uso de extern es útil si explícitamente desea evitar la definición de una variable.

Dejame explicar:

Digamos que el archivo ac contiene:

#include "a.h" int i = 2; int f() { i++; return i;}

El archivo ah incluye:

extern int i; int f(void);

y el archivo bc contiene:

#include <stdio.h> #include "a.h" int main(void){ printf("%d/n", f()); return 0; }

El extern en el encabezado es útil, porque le dice al compilador durante la fase de enlace, "esta es una declaración, y no una definición". Si elimino la línea en ac que define i, le asigna espacio y le asigna un valor, el programa no puede compilar con una referencia indefinida. Esto le dice al desarrollador que se ha referido a una variable, pero aún no la ha definido. Si, por otro lado, omito la palabra clave "extern" y elimino la línea int i = 2 , el programa aún se compila: se definirá con un valor predeterminado de 0.

Las variables de ámbito de archivo se definen implícitamente con un valor predeterminado de 0 o NULL si no les asigna un valor explícitamente, a diferencia de las variables de bloque de ámbito que declara en la parte superior de una función. La palabra clave extern evita esta definición implícita y, por lo tanto, ayuda a evitar errores.

Para funciones, en declaraciones de función, la palabra clave es de hecho redundante. Las declaraciones de funciones no tienen una definición implícita.

En C, no noté ningún efecto de la palabra clave extern utilizada antes de la declaración de la función. Al principio, pensé que al definir extern int f(); en un solo archivo te obliga a implementarlo fuera del alcance del archivo. Sin embargo, descubrí que ambos:

extern int f(); int f() {return 0;}

y

extern int f() {return 0;}

compilar bien, sin advertencias de gcc. gcc -Wall -ansi ; ni siquiera aceptaría // comentarios.

¿Hay algún efecto para utilizar las definiciones extern antes de las funciones ? O solo es una palabra clave opcional sin efectos secundarios para las funciones.

En este último caso, no entiendo por qué los diseñadores estándar eligieron ensuciar la gramática con palabras clave superfluas.

EDITAR: para aclarar, sé que hay uso para las variables extern , pero solo estoy preguntando por funciones extern .


Hasta donde recuerdo el estándar, todas las declaraciones de funciones se consideran como "externas" de forma predeterminada, por lo que no es necesario especificarlas explícitamente.

Eso no hace que esta palabra clave sea inútil, ya que también se puede usar con variables (y en ese caso, es la única solución para resolver problemas de vinculación). Pero con las funciones, sí, es opcional.


La palabra clave extern informa al compilador de que la función o variable tiene una vinculación externa; en otras palabras, que es visible desde archivos distintos a aquel en el que está definido. En este sentido, tiene el significado opuesto a la palabra clave static . Es un poco extraño poner extern en el momento de la definición, ya que ningún otro archivo tendría visibilidad de la definición (o daría lugar a múltiples definiciones). Normalmente se pone extern en una declaración en algún momento con visibilidad externa (como un archivo de encabezado) y se coloca la definición en otro lugar.


La palabra clave extern toma diferentes formas dependiendo del entorno. Si hay una declaración disponible, la palabra clave extern toma el enlace como el especificado anteriormente en la unidad de traducción. En ausencia de tal declaración, extern especifica un enlace externo.

static int g(); extern int g(); /* g has internal linkage */ extern int j(); /* j has tentative external linkage */ extern int h(); static int h(); /* error */

Aquí están los párrafos relevantes del borrador C99 (n1256):

6.2.2 Enlaces de identificadores

[...]

4 Para un identificador declarado con el especificador de especificación de clase de almacenamiento en un alcance en el que es visible una declaración previa de ese identificador, 23) si la declaración previa especifica una vinculación interna o externa, la vinculación del identificador en la declaración posterior es la misma como el enlace especificado en la declaración previa. Si no hay una declaración previa visible, o si la declaración previa no especifica ningún vínculo, entonces el identificador tiene una vinculación externa.

5 Si la declaración de un identificador para una función no tiene un especificador de clase de almacenamiento, su vinculación se determina exactamente como si se hubiera declarado con el especificador de clase de almacenamiento extern. Si la declaración de un identificador para un objeto tiene un alcance de archivo y no un especificador de clase de almacenamiento, su vinculación es externa.


La razón por la que no tiene ningún efecto es porque en el tiempo de enlace el enlazador intenta resolver la definición externa (en su caso extern int f() ). No importa si lo encuentra en el mismo archivo o en otro diferente, siempre que se encuentre.

Espero que esto responda a su pregunta.


Las funciones en línea tienen reglas especiales sobre lo que significa extern . (Tenga en cuenta que las funciones en línea son una extensión C99 o GNU, no estaban en la C.

Para funciones que no son en línea, extern no es necesario ya que está activado por defecto.

Tenga en cuenta que las reglas para C ++ son diferentes. Por ejemplo, se necesita una extern "C" en la declaración C ++ de las funciones C a las que se va a llamar desde C ++, y existen reglas diferentes sobre inline .


Tenemos dos archivos, foo.c y bar.c.

Aquí está foo.c

#include <stdio.h> volatile unsigned int stop_now = 0; extern void bar_function(void); int main(void) { while (1) { bar_function(); stop_now = 1; } return 0; }

Ahora, aquí está bar.c

#include <stdio.h> extern volatile unsigned int stop_now; void bar_function(void) { while (! stop_now) { printf("Hello, world!/n"); sleep(30); } }

Como puede ver, no tenemos un encabezado compartido entre foo.c y bar.c, sin embargo bar.c necesita algo declarado en foo.c cuando está vinculado, y foo.c necesita una función de bar.c cuando está enlazado.

Al usar ''extern'', le está diciendo al compilador que lo que le sigue se encontrará (no estático) en el momento del enlace; no reserve nada en el pase actual, ya que se encontrará más tarde. Las funciones y las variables se tratan por igual a este respecto.

Es muy útil si necesita compartir algo global entre módulos y no desea ponerlo / inicializarlo en un encabezado.

Técnicamente, cada función en un encabezado público de la biblioteca es ''extern'', sin embargo etiquetarlas como tal tiene muy poco o ningún beneficio, dependiendo del compilador. La mayoría de los compiladores pueden darse cuenta por sí mismos. Como puede ver, esas funciones en realidad están definidas en otro lugar.

En el ejemplo anterior, main () imprimirá hello world solo una vez, pero continuará ingresando bar_function (). También tenga en cuenta que bar_function () no va a regresar en este ejemplo (ya que es solo un ejemplo). Imagínese que stop_now se modificó cuando se repara una señal (por lo tanto, volátil) si esto no parece lo suficientemente práctico.

Los complementos son muy útiles para cosas como manejadores de señal, un mutex que no quieres poner en un encabezado o estructura, etc. La mayoría de los compiladores optimizarán para asegurar que no reserven memoria para objetos externos, ya que saben que Lo reservaré en el módulo donde se define el objeto. Sin embargo, una vez más, no tiene mucho sentido especificarlo con compiladores modernos al crear prototipos de funciones públicas.

Espero que ayude :)


declarar una función extern significa que su definición se resolverá en el momento de la vinculación, no durante la compilación.

A diferencia de las funciones normales, que no están declaradas de manera externa, se puede definir en cualquiera de los archivos fuente (pero no en múltiples archivos fuente, de lo contrario obtendrá un error de enlazador que indica que ha dado múltiples definiciones de la función) incluyendo el de que se declara extern. Así que, en su caso, el enlazador resuelve la definición de la función en el mismo archivo.

No creo que hacer esto sea muy útil, sin embargo, hacer este tipo de experimentos proporciona una mejor comprensión sobre cómo funciona el compilador y el enlazador del lenguaje.