Mejor respuesta
Como sabemos, se puede acceder a las funciones definidas en un archivo en otro archivo. Si queremos restringir que las funciones no deben ser llamadas en otro archivo, podemos hacerlas estáticas.
Por lo tanto, funciones estáticas son aquellas funciones que son invocables en el mismo archivo donde definen .
Podemos definir una función estática usando la siguiente sintaxis
static return\_type function\_name(arguments)
{
function\_body;
}
Aquí hay una función para encontrar la raíz cuadrada de un número dado
static long int getSquare(int num){
return (num*num);
}
Programa para demostrar un ejemplo de función estática en lenguaje C
#include
//static function definition
static long int getSquare(int num){
return (num*num);
}
int main()
{
int num;
printf("Enter an integer number: ");
scanf("\%d",&num);
printf("Square of \%d is \%ld.\n",num,getSquare(num));
return 0;
}
Salida
Enter an integer number: 36
Square of 36 is 1296.
¿Por qué son necesarias las funciones estáticas?
Dado que las funciones se utilizan para reutilizar el código (es decir el código que ha escrito puede acceder en otro archivo poniéndolos en las funciones ), pero cuando quiera definir algunos funciones que no deberían ser compartidas (invocables) en otro archivo .
Las funciones estáticas también son útiles para manejar problema de conflicto de declaración : si hay dos funciones en dos archivos diferentes con el mismo nombre, la declaración de la función entrará en conflicto. Podemos hacerlos estáticos.
Para cumplir con este tipo de requisito, podemos hacerlos estáticos .
Respuesta
Respuesta corta: Significa que el nombre de la función solo es visible y se puede llamar en el archivo que se está compilando actualmente. Otros archivos compilados por separado no verán el nombre de la función ni podrán llamarlo. Posteriormente, pueden tener sus propias funciones estáticas del mismo nombre. Esto evita conflictos de nombres en inclusiones de archivos y en la vinculación de archivos de objetos y bibliotecas binarias.
Hay 4 clases de almacenamiento diferentes para el almacenamiento en C.
- auto (automático) esto es «regular» (predeterminado) y usa la palabra clave auto , pero es normalmente no se especifica ya que es el predeterminado
- registro es una «pista» para el compilador de que puede optimizar el código creado para almacenar el valor en un registro de CPU para un procesamiento más rápido. El compilador lo intentará si puede hacerlo, pero si no es lo mismo que el normal.
- extern externo significa que hay solo una variable global con ese nombre, y todos los archivos que la declaren como externa usarán ese almacenamiento. Un archivo lo declarará globalmente como una variable regular, donde se asignará en la compilación.
- static Especificador de almacenamiento en archivos fuente C significa algunas cosas diferentes.
- El nombre y el almacenamiento no se exportan a otros archivos que se compilan al mismo tiempo. Esto permite que cada archivo tenga nombres idénticos que no entren en conflicto.
- El almacenamiento creado para la variable se crea en el área de almacenamiento estático y se inicializa a 0 al inicio del programa, o con un valor explícito.
- La inicialización de una variable estática se realiza solo una vez . (en el momento de la compilación). A partir de entonces, los valores asignados se mantienen durante la vida útil del programa o hasta que se modifican mediante una asignación.
- El almacenamiento estático declarado dentro de las funciones tiene un alcance de función, pero una asignación estática. Esto significa que el almacenamiento es permanente durante la vida del programa y no se crea cuando el marco de pila de funciones se asigna para la llamada de función. Conserva su valor a través de múltiples llamadas a funciones. El almacenamiento persiste aunque el bloque de código se recupere de la pila después de que regrese.
int accumulate( unsigned int x)
{
static unsigned int acc = 0;
acc = acc + x;
return acc;
}
- Lo anterior devolvería un recuento actual de su entrada, ya que var acc retendría el valor a través de cada llamada. acc se inicializará en 0 cuando se cargue el programa.
- Las variables estáticas tienen direcciones en la RAM, y puede enviarlas a funciones por referencia o valor.
- Las variables de menor alcance (definidas dentro de funciones) que tienen el mismo nombre que una variable estática fuera de ese alcance, sombrean la variable estática, al igual que cualquier otra.
- Las variables estáticas no pueden ser exportados a archivos externos, por lo que los valores pueden perderse en los dominios de compilación si no se envían explícitamente como parámetros por valor. (¡Entendido!)
- Como 4, otros archivos no pueden acceder a variables estáticas como extern como podrían hacerlo con variables automáticas (normales). No funcionará, obtendrá programas con errores que fallarán y el compilador podría engañarse y perderlo.
- Las variables estáticas pueden inicializarse en su declaración, pero el valor de inicialización debe ser una expresión constante, evaluable en tiempo de compilación, no es un valor que no sea calculable en tiempo de compilación. No puede inicializar una variable estática con un valor desconocido, como una variable de parámetro, o el resultado de una llamada de función que no se ha producido en el momento de la compilación.
int accumulate( unsigned int x)
{
/* ERROR x is not a compile-time constant. */
static unsigned int acc = x;
static unsigned int acc = 0; /* OK */
acc = acc + x;
return acc;
}
Funciones estáticas
- Una función estática en C tiene alcance de archivo . Una función estática no puede ser llamado por otro archivo en la misma unidad de traducción. Una unidad de traducción es todo el código fuente que va a un compilador después del preprocesamiento para ser compilado de una vez. Las funciones estáticas no pueden acceder a variables estáticas o llamar a funciones estáticas desde otros archivos. Entonces, si desea limitar el acceso a una función al archivo actual, puede hacerlo estático. Solo una función con ese nombre puede existir en ese archivo (que también se aplica a las funciones regulares), por lo que a menudo las funciones de utilidad se colocan en archivos de encabezado, para ser incluidas en múltiples compilaciones, y el encabezado está protegido con comandos de preprocesador para no incluirse en cualquier unidad de compilación más de una vez. Todos los encabezados de la biblioteca C estándar están llenos de funciones globales, y están protegidas para que se compilen solo una vez en una compilación y sean funciones globales. Sin funciones estáticas. Se dice que las funciones estáticas tienen «enlace interno» , lo que significa que no se pueden ver en otros módulos compilados, incluso si están enlazados al mismo programa o biblioteca final. Si una función no es estática entonces en C esa función es una función global y estará disponible en todo el programa globalmente. Esto significa que solo puede tener una función llamada print en todo el programa . Para evitar esto, convierta sus funciones y variables en estáticas y no tendrá un conflicto de nombres.
- Las funciones son globales y externas de forma predeterminada , excepto en el archivo en el que están definidas. Por lo tanto, no verá la palabra extern usado en fuente C con funciones, porque ya está implícitamente. Es por eso que puede llamar a funciones normales desde cualquier archivo en la unidad de traducción. Se dice que tienen enlace externo , lo que significa que una vez enlazados son visibles e invocables por cualquier archivo del módulo o cualquier otro módulo del programa enlazado.
- Una declaración de prototipo de función es una “definición tentativa”, que es implícitamente externa . El código después de escanear la declaración del prototipo por primera vez puede llamar a la función siempre que exista la definición completa en el código final. Eso significa que debe existir una «definición real» o la fase de enlace fallará. Es por eso que los encabezados en C generalmente no contienen el código fuente de las funciones, no son necesarios para compilar, pero están en la fase de vinculación.
- Una declaración de prototipo de función estática es una «definición tentativa», que explícitamente no es externa . La definición completa debe estar presente en la unidad de traducción actual (compilada al mismo tiempo) o la compilación fallará. Los compiladores de C modernos sintetizarán el prototipo a partir de la definición siempre que ocurra antes de una llamada de función real. Las llamadas «declaraciones hacia adelante» permiten el uso de definiciones provisionales con la definición real más adelante, y tienen varios usos en estructuras de datos y en la organización de bibliotecas.
- La primera definición de una firma de archivo es la que se usa para todo el programa, incluidos estático o externo. Una vez que una función se define por primera vez, si se declara inicialmente como estática, será estática siempre, incluso si se redefine más tarde sin la palabra clave estática. Si inicialmente se declara extern (predeterminado), no se puede redefinir como estático.
static void f(int); /* Function is always static */
...
void f(int x) { ….} /* static , not exported, no error */
void f(int); /* Function is always global */
...
static void f(int x) { ….} /*ERROR NOT STATIC */
clang: "error: static declaration of "f" follows non-static declaration"
- Las funciones definidas en el alcance del bloque no se pueden declarar estáticas. Solo se pueden realizar definiciones de funciones estáticas de ámbito de archivo fuera de cualquier bloque. Esto tiene sentido desde una perspectiva lógica, ya que el alcance del archivo no se puede hacer más pequeño que el archivo completo. Así que defina una función estática, o al menos el prototipo, muy temprano en el archivo.
- Static se refiere a la función, no al tipo de retorno . Puede colocar la palabra clave estática después del tipo de retorno si lo desea, pero si lo hace, es extraño y confundirá a la gente. El valor de retorno no es estático, la función es.
- Una definición de función estática no anulará una global uno definido antes en el mismo archivo o en un archivo incluido. Si ya existe una función con ese nombre definido, no puede redefinirla con una función estática o con cualquier función del mismo nombre.
C no cambia el nombre de las funciones y las variables internamente como lo hace C ++, por lo que no admite la sobrecarga de funciones. C ++ «mutila» los nombres de las funciones con un nombre codificado que indica varios tipos de datos adicionales, como si es parte de una clase o cuáles son sus parámetros, etc. Por lo tanto, en C sin la palabra clave estática, es posible que solo tenga una función de cada nombre único en un programa, sin importar cuántos archivos o bibliotecas implique.
Entonces, ¿qué debe hacer si desea cambiar su función por una que ya existe?
Bueno, lo que hacen los codificadores C inteligentes es crear un nombre diferente para su función. Pero hay una manera de engañar al compilador cambiando preventivamente el texto fuente con el preprocesador.
Ejemplo: Un idiota escribió una función int sort( char** Array)
en su biblioteca y lo hizo global, y tiene errores y no hace exactamente lo que usted quiere, porque hace que los números vengan después de las letras o algo así, y las palabras con T siempre están primero, por alguna razón.
Usted quiere usa la biblioteca pero necesita arreglar la función, y solo tiene los encabezados y la biblioteca compilada, no el código fuente.
OK> por lo que se crea un encabezado «especial» que reemplaza todas las instancias de » sort ”con“ bad\_sort ”en el encabezado, luego importa su código y reemplaza todas las instancias de“ sort ”con“ good\_sort ”. «Good\_sort» se define completamente en good\_sort.h, pero está marcado como estático, por lo que solo se conoce en el archivo en el que está incluido.
/* good\_sort.h */
#ifndef \_GOOD\_SORT\_H
#define \_GOOD\_SORT\_H
static int good\_sort(char** Array)
{
... //code here
return numsorted;
}
#endif
Se agrega un corchete de protección de definición para asegurarse de que no se incluya dos veces.
/*-----------------------------------*/
/* program.c */
#include "Trumpsort.h" /* The buggy library header */
...
#ifdef sort
#undef sort /* undefine the sort function name as reserved */
#define sort bad\_sort /* replace the name */
#include "good\_sort.h" /* your fixed version */
#endif
#define sort good\_sort /* replace the name in this file */
/* rest of file */
Un poco de mierda, pero la idea es llamar a tu función en lugar del malo de renam en «good\_sort» y llamarlo en su lugar. (pero solo en este archivo – static ).