2010-08-20 10 views
5

Estoy tratando de instrumentar algún código para capturar e imprimir mensajes de error. Actualmente estoy usando una macro somethng así:Uso y devolución de salida en macro C

#define my_function(x) \ 
    switch(function(x)) { \ 
    case ERROR: \ 
     fprintf(stderr, "Error!\n"); \ 
     break; \ 
    } 

Normalmente, nunca capturar la salida de función y esto funciona bien. Pero he encontrado un par de casos en los que también necesito el valor de retorno de function(). Intenté algo como lo siguiente, pero esto produce un error de sintaxis.

#define my_function(x) \ 
    do { \ 
    int __err = function(x); \ 
    switch(__err) { \ 
     case ERROR: \ 
     fprintf(stderr, "Error!\n"); \ 
     break; \ 
    } \ 
    __err; \ 
    } while(0) 

pude declarar una variable global para mantener el valor de retorno de la función, pero que se ve feo y mi programa es multiproceso, por lo que es probable que cause problemas. Espero que haya una mejor solución por ahí.

+1

¿Por qué no lo hace una función en línea? – Job

+1

La "salida" de una función no es lo mismo que el "valor de retorno" de una función. Quieres el valor de retorno –

+2

A su publicación le faltan varios marcadores de continuación de línea. Ese puede ser su error de sintaxis. –

Respuesta

6

Este es un código relativamente complicado, no hay muchas razones para tenerlo en una macro. Hazlo inline (C99) o static (C89) o ambos si realmente deseas colocarlo en un archivo de encabezado. Con cualquier compilador razonable, esto debería dar como resultado la misma eficacia que una macro.

+0

Desafortunadamente, una función en línea no puede hacer algunos de los trucos que puede realizar una macro, como concatenar identificadores ('FOO ## _size' de algún código generado que estoy usando, por ejemplo). De lo contrario, sí, use funciones en línea. – thirtythreeforty

1

Falta 2 en su segunda expresión (líneas 2 y 3), ¿es correcto?

+0

Lo sentimos, simplemente errores tipográficos –

+0

+1 No hay razón para rechazar esta respuesta –

+0

Acabo de rechazar porque esto no responde a la pregunta ya que el error de sintaxis no estaba relacionado con los errores tipográficos. –

25

GCC tiene una característica llamada statement expressions

Así que si definen como macro

#define FOO(A) ({int retval; retval = do_something(A); retval;}) 

que usted será capaz de utilizar como como

foo = FOO(bar); 
+1

Eso es básicamente lo que estaba tratando de hacer con lo anterior. Creo que @Jens tenía razón en que una función en línea se adapta mejor a mis necesidades. –

1

Lo sentimos, esta es una edición ..

  1. Creo que solo necesitas las llaves. No es necesario utilizar las palabras clave ...
  2. Asegúrese de que las barras diagonales inversas sean los últimos caracteres en cada línea (sin espacio después).
  3. Si usted necesita para obtener el valor err fuera de la macro, puede simplemente añadir un parámetro

así:

#define my_function(x, out) \ 
     { \ 
     int __err = function(x); \ 
     switch(__err) { \ 
      case ERROR: \ 
      fprintf(stderr, "Error!\n"); \ 
      break; \ 
     } \ 
     __err; \ 
     (*(out)) = _err; \ 
     } 

Para conservar el paradigma C pase por referencia, se deben llamar mi_funcion esta manera:

int output_err; 

my_function(num, &output_err); 

de esta manera, más adelante, si usted decide hacer mi_funcion una función real, que no es necesario cambiar las referencias de llamada.

Btw, qrdl "Expresiones de extracto" también es una buena manera de hacerlo.

-1

no hay necesidad de declarar la variable si su función devuelve algo, entonces puede obtener ese valor directamente. Por ejemplo:

#define FOO(A) do_something(A) 

Aquí do_ algo devuelve un número entero. Entonces puede usarlo fácilmente como:

int a = FOO(a); 
+1

Esto no funciona en esta situación, ya que la macro también necesita usar la salida de 'do_something' y la única manera de seguir el enfoque que sugiere es llamar a' do_something' dos veces. –

3

Una respuesta muy tardía. Pero no obstante.Estoy de acuerdo con que las funciones en línea son mejores, pero las MACRO ofrecen una gran diversión de impresión que no se puede obtener con las funciones en línea. Estoy de acuerdo con @qrdl en que puedes usar expresiones de enunciado si hubieras reestructurado un poco tus declaraciones. Así es como funcionaría con un macro -

#define my_function(x, y) ({ \ 
    int __err = 0; \ 
    do { \ 
    __err = function(x, y); \ 
    switch(__err) { \ 
     case ERROR: \ 
     fprintf(stderr, "Error!\n"); \ 
     break; \ 
    } \ 
    } while(0); \ 
    __err; \ 
}) 
+0

'({...})' ¿funciona en cualquier compilador? es una extensión de GNU C https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html – JuanPablo

+1

¿No es inútil el do-while aquí? – Traummaennlein