Respuestas:
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
(con o sin inline
) 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ón
inline
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 las static inline
funciones.
El inline
especificador (como la register
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
y register
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: una inline
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 de register
variables calificadas.
Personalmente, también uso la convención para marcar static
las definiciones de funciones dentro de los encabezados inline
, 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 y static const
objetos además de las extern
declaraciones dentro de los encabezados.
Nunca he escrito una inline
función con una clase de almacenamiento diferente de static
.
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
y static inline
difiere en una forma en que el compilador emite advertencias sobre las funciones no utilizadas. Más precisamente, cuando declara la static
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 a static 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. Y static 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.
warning: unused function 'function' [clang-diagnostic-unused-function]
una static inline
función al clang-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 combinar static
& 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
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 las static
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 siempre inline
para static
funciones en encabezados.
inline
en definición? ¿También implica no usarlo para extern
funciones?
attribute((used))
y su uso para permitir que asm haga referencia a static
funciones y datos que de otro modo no estarían referenciados .
static
refiere al alcance. En C significa que la función / variable solo puede usarse dentro de la misma unidad de traducción.