Macros V/S funciones en línea durante la programación para avr-gcc

He estado haciendo mi primer trabajo serio de programación en estos días. He estado expuesto a una gran cantidad de código de diferentes desarrolladores. Una cosa que encuentro confusa es cómo deciden estos desarrolladores cuándo usar una definición de macro y cuándo usar una función en línea. Ambos tienen esencialmente la misma función, colocan un cierto código en el lugar desde el que son llamados. Entonces, ¿hay alguna lógica para la selección o es solo un capricho del desarrollador?

(Estoy hablando aquí de macros para funciones y no de constantes).

Puede obtener respuestas más detalladas de stackoverflow para este tipo de pregunta.
Pensé en publicarlo allí, pero pensé que como esto sería más específico para los sistemas integrados, debería publicarlo aquí.

Respuestas (2)

Hay muchos beneficios para las funciones en línea sobre las macros de preprocesador:

  • Comprobación de tipos . El compilador se quejará si los argumentos son de tipo incorrecto.
  • Sin riesgo de evaluación múltiple : las macros pueden ser peligrosas cuando el argumento es una expresión, considere:

    #include <stdio.h>
    #define square(n) ((n)*(n))
    
    int main(void)
    {
        int x, i = 0;
        while (i < 10) {
            x = square(i++);
            printf("%d\r\n", x);
        }
        return 0;
    }
    
  • Puede incluir varias líneas de código sin retrocesos finales.
  • Las funciones en línea tienen su propio alcance para las variables y pueden devolver un valor .

Las macros pueden ser útiles, por ejemplo, al concatenar tokens en código, para simplificar algunas declaraciones complejas.

Considere las macros como una simple funcionalidad de reemplazo de texto tonto. Una buena regla general es evitar macros similares a funciones, a menos que no haya otra solución viable .

Es un error común pensar que la inserción siempre equivale a un código más rápido. Tenga en cuenta que cada llamada en línea desde más de un lugar suma el tamaño del código . La optimización prematura no es una virtud, incluso cuando se trabaja con los recursos limitados de un microcontrolador.

GCC interpreta la inlinepalabra clave como una mera pista. No hay garantía de que la función realmente esté en línea. Para tener GCC en línea con su función, independientemente del nivel de optimización, declare la función con el always_inlineatributo:

void function() __attribute__((always_inline));

Las funciones en línea pueden o no estar en línea por el compilador. Las macros, por otro lado, son manejadas por el precompilador y, por lo tanto, se garantiza que estarán en línea (código replicado). A menudo, uno usará una macro para una operación corta pero compleja para agregar legibilidad al código, sin penalizar el rendimiento por una llamada de función. Por ejemplo:

#define SWAP(a,b)({a ^= b; b ^= a; a ^= b;})

... proporciona una forma de intercambiar variables ayb sin una llamada de función y sin una variable temporal.

Hay una pregunta de stackoverflow con el mismo efecto (aunque no específicamente sobre avr-gcc).