lenguaje incluir headers hacer encabezados ejemplos crear como cabeceras cabecera archivos c function static

incluir - headers en c



C/C++: función estática en el archivo de encabezado, ¿qué significa? (6)

Sé lo que significa cuando la función estática se declara en el archivo fuente. Estoy leyendo un código, encontré que la función estática en los archivos de encabezado podría invocarse en otros archivos.


¿La función está definida en el archivo de encabezado? Para que el código real se proporcione directamente en la función, así:

static int addTwo(int x) { return x + 2; }

Entonces esa es solo una forma de proporcionar una función útil a muchos archivos C diferentes. Cada archivo C que incluye el encabezado obtendrá su propia definición a la que puede llamar. Esto, por supuesto, desperdicia memoria, y es (en mi opinión) algo bastante feo, ya que tener un código ejecutable en un encabezado generalmente no es una buena idea.

Recuerde que #include : ing un encabezado básicamente solo pega el contenido del encabezado (y cualquier otro encabezado incluido) en el archivo C como lo ve el compilador. El compilador nunca sabe que la definición de una función particular provino de un archivo de encabezado.

ACTUALIZACIÓN : en muchos casos, en realidad es una buena idea hacer algo como lo anterior, y me doy cuenta de que mi respuesta suena muy en blanco y negro sobre esto, lo que es un poco simplificar un poco las cosas. Por ejemplo, el código que modela (o solo usa) funciones intrínsecas se puede expresar como el anterior, y con una palabra clave en inline explícita incluso:

static inline int addTwo(int *x) { __add_two_superquickly(x); }

Aquí, la función __add_two_superquickly() es una ficción intrínseca, y como queremos que toda la función se compile básicamente en una sola instrucción, realmente queremos que esté en línea. Aún así, lo anterior es más limpio que usar una macro.

La ventaja sobre el solo uso de lo intrínseco directamente es, por supuesto, que envolverlo en otra capa de abstracción hace posible construir el código en compiladores que carecen de ese intrínseco particular, proporcionando una implementación alternativa y seleccionando la correcta dependiendo de qué compilador se esté utilizando. .


Como otros dicen, tiene exactamente el mismo significado que una función static en el archivo .c mismo. Esto se debe a que no hay diferencia semántica entre los archivos .c y .h ; solo existe la unidad de compilación formada por el archivo realmente pasado al compilador (generalmente denominado .c ) con los contenidos de todos los archivos nombrados en #include líneas de #include (generalmente llamadas .h ) insertadas en la secuencia tal como las ve. el preprocesador

La convención de que la fuente C está en un archivo llamado .c y las declaraciones públicas están en archivos llamados .h es solo una convención. Pero generalmente es bueno. Según esa convención, las únicas cosas que deberían aparecer en los archivos .h son las declaraciones, de modo que generalmente se evita tener el mismo símbolo definido más de una vez en un solo programa.

En este caso particular, la palabra clave static hace que el símbolo sea privado para el módulo, por lo que no hay un conflicto de definición múltiple en espera de causar problemas. Entonces, en ese sentido, es seguro hacerlo. Pero a falta de una garantía de que la función esté en línea, usted corre el riesgo de que la función sea instanciada en cada módulo que ocurra para #include ese archivo de cabecera que, en el mejor de los casos, es una pérdida de memoria en el segmento de código.

No estoy seguro de qué casos de uso justificarían hacer esto en absoluto en un encabezado público generalmente disponible.

Si el archivo .h es un código generado y solo se incluye en un solo archivo .c , entonces yo personalmente nombraría el archivo como algo distinto de .h para enfatizar que no es en realidad un encabezado público. Por ejemplo, una utilidad que convierta un archivo binario en una definición de variable inicializada podría escribir un archivo destinado a ser utilizado a través de #include y podría contener una declaración static de la variable, y posiblemente incluso definiciones static de accesor u otras relacionadas. funciones de utilidad.


Creará efectivamente una función estática separada con el mismo nombre dentro de cada archivo cpp en el que esté incluido. Lo mismo se aplica a las variables globales.


Es útil en algunas bibliotecas de "solo encabezado" con pequeñas funciones en línea. En tal caso, siempre desea hacer una copia de la función, por lo que este no es un mal patrón. Sin embargo, esto le brinda una manera fácil de insertar partes separadas de interfaz e implementación en el único archivo de encabezado:

// header.h // interface part (for user?!) static inline float av(float a, float b); // implementation part (for developer) static inline float av(float a, float b) { return (a+b)/2.f; }

La biblioteca matemática de vectores de Apple en el marco GLK utiliza dicha construcción (por ejemplo, GLKMatrix4.h).


No existe una diferencia semántica en la definición en el archivo de origen o el archivo de encabezado; básicamente, ambos significan lo mismo en C simple cuando se utiliza una palabra clave estática que limita el alcance.

Sin embargo, hay un problema al escribir esto en el archivo de encabezado, esto es porque cada vez que incluye el encabezado en un archivo fuente tendrá una copia de la función con la misma implementación que es muy similar a tener una función normal definida en el encabezado archivo. Al agregar la definición en el encabezado, no está logrando el propósito de la función estática.

Por lo tanto, sugiero que debe tener su implementación solo en su archivo de origen y no en el encabezado.


Si define la función en un archivo de encabezado (no simplemente lo declara), se generará una copia de la función en cada unidad de traducción (básicamente en cada archivo cpp que incluya este encabezado).

Esto puede aumentar el tamaño de su ejecutable, pero esto puede ser insignificante si la función es pequeña. La ventaja es que la mayoría de los compiladores pueden alinear la función, lo que puede aumentar el rendimiento del código.

Pero puede haber una gran diferencia al hacer esto que no se mencionó en ninguna respuesta. Si su función usa una variable local estática tal como:

static int counter() { static int ctr = 0; return ctr++; }

Más bien que:

//header int counter(); //source int counter() { static int ctr = 0; return ctr++; }

Entonces, cada archivo fuente que incluya este encabezado tendrá su propio contador. Si la función se declara dentro del encabezado y se define en un archivo fuente, el contador se compartirá en todo el programa.

Entonces, diciendo que la única diferencia será el rendimiento y el tamaño del código es incorrecto.