"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > Funciones en línea en C y C++

Funciones en línea en C y C++

Publicado el 2024-11-08
Navegar:801

Inline Functions in C and C

Introducción

C agregó la palabra clave en línea que puede anteponer una definición de función, como:

inline int max_int( int a, int b ) {
    return a > b ? a : b;
}

para darle al compilador una “pista” de que el programa en general podría beneficiarse en rendimiento si la función está incluida.

Se ha expandido el código de una función que ha sido incluida en cada punto en el que se ha llamado en lugar de realizar el mecanismo normal de llamada a función de:

  • Guardando registros.
  • Enviar valores de argumentos a la pila.
  • Ejecutando la instrucción de llamada.
  • La función que finalmente ejecuta la instrucción ret.
  • Restaurando registros.

Para funciones muy pequeñas, la incorporación en línea puede generar una ganancia de rendimiento. Pero como casi todo lo demás, existen compensaciones.

La palabra clave en línea se transfirió a C99, pero con requisitos ligeramente diferentes; hablaremos más adelante.

Diferencias con las macros

Las funciones en línea son como macros similares a funciones (y están destinadas a reemplazar muchos usos de ellas). Generalmente, esto es bueno porque las funciones en línea son funciones y tienen una semántica de función completa en lugar de una mera sustitución de texto realizada por el preprocesador que no entiende ni C ni C.

Una macro ingenuamente equivalente a la función max_int():

#define MAX_INT(A,B)  A > B ? A : B  /* bad implementation */

tiene los siguientes problemas:

  • Los argumentos ampliados, por ejemplo, MAX(n & 0xFF, 8), pueden dar como resultado una precedencia de operador incorrecta.
  • Los argumentos que tienen efectos secundarios, por ejemplo, MAX(n , 8), pueden tener múltiples efectos secundarios.
  • No hay verificación de tipo de los argumentos en la definición.
  • Los errores suelen ser detallados y difíciles de leer.

Además, una macro:

  • Puede modificar su argumento (que a menudo no es lo que desea).

Las funciones en línea no tienen ninguno de estos problemas pero pueden generar el mismo beneficio de rendimiento. Por lo tanto, utilice funciones en línea en lugar de macros similares a funciones.

Sólo una pista

Como se mencionó, especificar en línea es solo una "pista" para el compilador de que el programa en general podría beneficiarse en el rendimiento de la función incorporada. El compilador es libre de ignorar la pista.

¿Por qué? Porque hay casos en los que o no es una buena idea o es imposible. Una función no está integrada o normalmente no está integrada cuando se cumple cualquiera de las siguientes condiciones:

  • La función es “demasiado grande”.
  • Llamas a la función mediante un puntero a función.
  • La función es recursiva.
  • La función tiene un bucle.

Puede haber otras razones. Todo depende en gran medida de la función, sus argumentos, el compilador y las opciones que se le den.

Si el compilador no puede o elige no incluir una función, no le advierte que no lo ha hecho (de forma predeterminada). Algunos compiladores, por ejemplo, gcc, tienen una opción -Winline que le advertirá y le dará la razón por la cual una función no estaba incorporada.

Especificar en línea es similar al código anterior que especifica registro; ambos son solo sugerencias.

Cuándo (y cuándo no) incorporarlo

Para la mayoría de las funciones, la mayor parte del costo de ejecutar la función está en el cuerpo de la función, no en el mecanismo de llamada a la función. Por lo tanto, para que una función sea una buena candidata para la inserción, generalmente tiene que ser:

  • Lo suficientemente pequeño como para que domine el costo del mecanismo de llamada a función.
  • Se utiliza en lugares donde el rendimiento realmente importa, por ejemplo, en bucles cerrados.

En caso de duda, perfila tu código. Usar en línea no una palabra clave mágica para "hacerme más rápido". Además, el uso excesivo de elementos en línea puede generar un exceso de código que, además, empeora el rendimiento de su programa en general.

Para obtener más información, consulte La enfermedad en línea.

Las funciones que suelen ser buenas candidatas para la incorporación incluyen:

  • “frases ingeniosas” como “captadores” y “definidores”.
  • Envoltorios simples para llamadas a otras funciones que proporcionan valores específicos para argumentos o realizan conversiones.

Una función en línea ideal aumenta el rendimiento y disminuye el tamaño del código.

Sin embargo, una advertencia para cualquier función en línea es que si su definición cambia, será necesario volver a compilar todo el código que la utiliza.

Optimizaciones en línea

Si el compilador realmente incluye una función en línea, entonces, además de omitir el código para el mecanismo normal de llamada a función, el compilador también puede:

  • Eliminar completamente uno o más argumentos de función cuyos valores sean constantes mediante direccionamiento inmediato.
  • Realice mejores optimizaciones que abarquen el código en el que está integrada la función y que normalmente no podría realizarse a través de los límites de la función.

Definición de función en línea

Para que el compilador pueda incorporar una función, debe poder “ver” su definición (no solo su declaración) en cada archivo .c o .cpp en el que se utiliza. como una macro. Por lo tanto, una función en línea debe estar definida en un archivo de encabezado.

Normalmente, una función, como todo lo demás, debe tener exactamente una definición al adherirse a la regla de una definición (ODR). Sin embargo, dado que la definición de una función en línea se "ve" en varios archivos .c o .cpp, el ODR se suspende para esa función.

Es posible tener diferentes definiciones para funciones en línea que tienen el mismo nombre, pero esto da como resultado un comportamiento indefinido ya que el compilador no tiene forma de verificar que todas las definiciones sean iguales.

Para insertar una función en C, todo lo que necesita hacer es prefijar la definición de la función con inline, eso es todo. El compilador y/o vinculador descartará automáticamente todas las definiciones menos una del archivo ejecutable final.

Sin embargo, para alinear una función en C, además debe decirle explícitamente al compilador en qué archivo .o colocar la definición en caso de que el compilador no pueda o no quiera alinear una función mediante externo en línea.

Por ejemplo, en exactamente un archivo .c, declararías una función como:

// util.c
extern inline int max_int( int, int );

Eso le dice al compilador que "ponga una definición para max_int() en util.o".

Como alternativa, en C, también puedes declarar estática una función en línea:

static inline int max_int( int a, int b ) {
    return a > b ? a : b;
}

Si haces esto, entonces:

  • No no tienes que declarar una función externa en línea en ningún lugar.
  • Sin embargo, si el compilador no incluye una función, generará una definición en cada archivo .c en el que se incluya nuevamente, lo que provocará un exceso de código.
  • Si la función tiene variables locales estáticas, cada definición tendrá copias distintas (que pueden ser o no lo que desea).

Conclusión

Las funciones en línea, si se usan con prudencia, pueden generar mejoras en el rendimiento. Generalmente, sólo las funciones muy pequeñas son ​​buenas candidatas para la inserción.

A partir de C 11, las funciones en línea también se pueden declarar constexpr, pero esa es una historia para otro momento.

Referencias

  • Estilo de codificación del kernel de Linux, §15 La enfermedad en línea.
  • Mito y realidad sobre el inline en C99.
  • Manual de referencia de C anotado, Margaret A. Ellis & Bjarne Stroustrup, Addison-Wesley, 1990, ISBN 0-201-51459-1, §7.1.2 Especificadores de funciones, págs. 99–105.
Declaración de liberación Este artículo se reproduce en: https://dev.to/pauljlucas/inline-functions-in-c-and-c-2040 Si hay alguna infracción, comuníquese con [email protected] para eliminarla.
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3