Los dos IMO hacen que la función tenga un alcance de la unidad de traducción solamente.
¿Cuál es la diferencia entre la función "estática" y "estática en línea"?
¿Por qué debería inline
colocarse en un archivo de encabezado, no en un .c
archivo?
inline
indica al compilador que intente incrustar el contenido de la función en el código de llamada en lugar de ejecutar una llamada real.
Para funciones pequeñas que se llaman con frecuencia que pueden marcar una gran diferencia de rendimiento.
Sin embargo, esto es solo una "pista", y el compilador puede ignorarlo, y la mayoría de los compiladores intentará "en línea" incluso cuando no se use la palabra clave, como parte de las optimizaciones, cuando sea posible.
por ejemplo:
static int Inc(int i) {return i+1};
.... // some code
int i;
.... // some more code
for (i=0; i<999999; i = Inc(i)) {/*do something here*/};
Este ciclo cerrado realizará una llamada a la función en cada iteración, y el contenido de la función en realidad es significativamente menor que el código que el compilador necesita poner para realizar la llamada. inline
esencialmente le indicará al compilador que convierta el código anterior en un equivalente de:
int i;
....
for (i=0; i<999999; i = i+1) { /* do something here */};
Saltarse la llamada a la función real y regresar
Obviamente, este es un ejemplo para mostrar el punto, no una pieza de código real.
static
se refiere al alcance. En C significa que la función / variable solo puede usarse dentro de la misma unidad de traducción.
static
refiere al alcance. En C significa que la función / variable solo puede usarse dentro de la misma unidad de traducción.static
(con o sininline
) puede estar en el encabezado perfectamente bien, no veo ninguna razón por la que no. Las plantillas son para C ++, esta pregunta es sobre C.inline
es un buen estilo, en mi opinióninline
no le indica al compilador que haga ningún intento de alineación. Simplemente le permite al programador incluir el cuerpo de la función en múltiples unidades de traducción sin violación de ODR. Un efecto secundario de esto es que es hace posible que el compilador, cuando sería inline la función, que lo hacen realmente.Por defecto, una definición en línea solo es válida en la unidad de traducción actual.
Si la clase de almacenamiento es
extern
, el identificador tiene un enlace externo y la definición en línea también proporciona la definición externa.Si la clase de almacenamiento es
static
, el identificador tiene un enlace interno y la definición en línea es invisible en otras unidades de traducción.Si la clase de almacenamiento no está especificada, la definición en línea solo es visible en la unidad de traducción actual, pero el identificador todavía tiene un enlace externo y se debe proporcionar una definición externa en una unidad de traducción diferente. El compilador es libre de usar la definición en línea o externa si la función se llama dentro de la unidad de traducción actual.
Como el compilador es libre de incorporar (y no incluir) cualquier función cuya definición sea visible en la unidad de traducción actual (y, gracias a las optimizaciones de tiempo de enlace, incluso en diferentes unidades de traducción, aunque el estándar C realmente no tiene en cuenta eso), para la mayoría de los propósitos prácticos, no hay diferencia entre las definiciones
static
y lasstatic inline
funciones.El
inline
especificador (como laregister
clase de almacenamiento) es solo una pista del compilador, y el compilador es libre de ignorarlo por completo. Los compiladores no optimizadores que cumplen con los estándares solo tienen que respetar sus efectos secundarios, y los compiladores optimizadores harán estas optimizaciones con o sin sugerencias explícitas.inline
yregister
no son inútiles, ya que le indican al compilador que arroje errores cuando el programador escribe un código que haría imposibles las optimizaciones: unainline
definición externa no puede hacer referencia a identificadores con enlace interno (ya que estos no estarían disponibles en una unidad de traducción diferente) o defina variables locales modificables con una duración de almacenamiento estática (ya que no compartirían el estado entre las unidades de traducción), y no puede tomar direcciones deregister
variables calificadas.Personalmente, también uso la convención para marcar
static
las definiciones de funciones dentro de los encabezadosinline
, ya que la razón principal para poner las definiciones de funciones en los archivos de encabezado es hacer que sean integrables.En general, solo uso definiciones de
static inline
funciones ystatic const
objetos además de lasextern
declaraciones dentro de los encabezados.Nunca he escrito una
inline
función con una clase de almacenamiento diferente destatic
.fuente
inline
como si realmente se aplicara a la alineación es engañosa y podría decirse que es incorrecta. Ningún compilador moderno lo utiliza como una sugerencia para alinearlo o requerirlo para permitir la inserción de una función.Según mi experiencia con GCC, lo sé
static
ystatic inline
difiere en una forma en que el compilador emite advertencias sobre las funciones no utilizadas. Más precisamente, cuando declara lastatic
función y no se usa en la unidad de traducción actual, el compilador genera una advertencia sobre la función no utilizada, pero puede inhibir esa advertencia al cambiarla astatic inline
.Por lo tanto, tiendo a pensar que
static
debería usarse en unidades de traducción y me beneficiaré del compilador de verificación adicional para encontrar funciones no utilizadas. Ystatic inline
debe usarse en archivos de encabezado para proporcionar funciones que puedan estar alineadas (debido a la ausencia de enlaces externos) sin emitir advertencias.Lamentablemente no puedo encontrar ninguna evidencia para esa lógica. Incluso a partir de la documentación de GCC no pude concluir que
inline
inhibe las advertencias de funciones no utilizadas. Agradecería si alguien compartiera enlaces a la descripción de eso.fuente
warning: unused function 'function' [clang-diagnostic-unused-function]
unastatic inline
función alclang-tidy
compilar con (v8.0.1), que se usa en otra unidad de traducción. Pero definitivamente, esta es una de las mejores explicaciones y razones para combinarstatic
&inline
!En C,
static
significa que la función o variable que defina solo se puede usar en este archivo (es decir, la unidad de compilación)Entonces,
static inline
significa la función en línea que solo se puede utilizar en este archivo.EDITAR:
La unidad de compilación debe ser La Unidad de Traducción
fuente
the compile unit
es algo que escribí por error, no existe tal cosa, la terminología real estranslation unit
Una diferencia que no está en el nivel del lenguaje sino en el nivel de implementación popular: ciertas versiones de gcc eliminarán las
static inline
funciones no referenciadas de la salida de forma predeterminada, pero mantendrán lasstatic
funciones simples incluso si no están referenciadas. No estoy seguro de a qué versiones se aplica esto, pero desde un punto de vista práctico significa que puede ser una buena idea usar siempreinline
parastatic
funciones en encabezados.fuente
inline
en definición? ¿También implica no usarlo paraextern
funciones?attribute((used))
y su uso para permitir que asm haga referencia astatic
funciones y datos que de otro modo no estarían referenciados .