una - ¿Por qué esta macro se define como({1;})?
que es una macro programada (3)
¿Por qué esta macro se define como ({1;})?
Todo depende del estilo de codificación del programador. Todo lo que hace es devolver el valor 1. Por ejemplo, en el arco x86
en " include/asm-generic/clkdev.h
", __clk_get
se define como
static inline int __clk_get(struct clk *clk) { return 1; }
También en linux / arch / c6x / include / asm / clkdev.h
static inline int __clk_get(struct clk *clk)
{
return 1;
}
En múltiples back-end ARM de Linux, estoy viendo en los archivos clkdev.h
esta definición de macro:
#define __clk_get(clk) ({ 1; })
Véase, por ejemplo, ./arch/arm/mach-versatile/include/mach/clkdev.h
Esta macro utiliza declaraciones de extensión GCC y declaraciones en expresiones
Más tarde, esta macro se utiliza en el archivo ./drivers/clk/clkdev.c , en la función clk_get_sys()
if (cl && !__clk_get(cl->clk))
cl = NULL;
Me pregunto por qué no usar aquí una macro simple:
#define __clk_get(clk) (1)
EDITAR:
He encontrado otro uso de esta construcción en las fuentes del kernel utilizando el siguiente patrón grep:
grep -R ''({[[:space:]]*[a-zA-Z0-9_()+=/!&*>., ?:-]/+[[:space:]]*;[[:space:]]*})'' .
Aquí están algunos de los partidos:
./kernel/trace/trace_selftest.c:# define trace_selftest_startup_dynamic_tracing(trace, tr, func) ({ 0; })
./kernel/profile.c:#define create_hash_tables() ({ 0; })
./include/asm-generic/bug.h: * Use of ({0;}) because WARN_ON_SMP(x) may be used either as
./include/asm-generic/bug.h:# define WARN_ON_SMP(x) ({0;})
./include/linux/key.h:#define key_get(k) ({ NULL; })
./include/linux/key.h:#define key_get(k) ({ NULL; })
./include/linux/audit.h:#define audit_alloc(t) ({ 0; })
./include/linux/audit.h:#define audit_bprm(p) ({ 0; })
./include/linux/audit.h:#define audit_sockaddr(len, addr) ({ 0; })
./include/linux/audit.h:#define audit_log_bprm_fcaps(b, ncr, ocr) ({ 0; })
./include/linux/audit.h:#define audit_log_start(c,g,t) ({ NULL; })
./include/linux/atalk.h:#define atalk_proc_init() ({ 0; })
./include/linux/ftrace.h:#define register_ftrace_function(ops) ({ 0; })
./include/linux/ftrace.h:#define unregister_ftrace_function(ops) ({ 0; })
./include/linux/ftrace.h:#define ftrace_regex_open(ops, flag, inod, file) ({ -ENODEV; })
./include/linux/ftrace.h:#define ftrace_set_filter(ops, buf, len, reset) ({ -ENODEV; })
./include/linux/ftrace.h:#define ftrace_set_notrace(ops, buf, len, reset) ({ -ENODEV; })
./include/linux/cpu.h:#define unregister_hotcpu_notifier(nb) ({ (void)(nb); })
./include/linux/proc_fs.h:#define proc_net_fops_create(net, name, mode, fops) ({ (void)(mode), NULL; })
./arch/powerpc/include/asm/pgtable-ppc64.h:#define pgd_set(pgdp, pudp) ({pgd_val(*(pgdp)) = (unsigned long)(pudp);})
./arch/sh/math-emu/math.c:#define WRITE(d,a) ({if(put_user(d, (typeof (d)*)a)) return -EFAULT;})
./arch/sh/math-emu/math.c:#define READ(d,a) ({if(get_user(d, (typeof (d)*)a)) return -EFAULT;})
[...]
Nota: la construcción ({if(put_user(d, (typeof (d)*)a)) return -EFAULT;})
parece ser un buen uso de la declaración compuesta. Pero esto también puede reemplazarse por do { if(put_user(d, (typeof (d)*)a)) return -EFAULT; } while(0)
más típico do { if(put_user(d, (typeof (d)*)a)) return -EFAULT; } while(0)
do { if(put_user(d, (typeof (d)*)a)) return -EFAULT; } while(0)
Una coincidencia devuelta por grep
es interesante: en ./include/asm-generic/bug.h hay un comentario sobre el uso de ({ 0; })
. Esta es la misma answer de AndreyT .
De hecho, uno no puede usar ((void)0)
, ya que no se podrá utilizar como valor r. ({ 0; })
está trabajando en cada caso.
Entonces, si tiene una macro que se puede usar como una función que devuelve un valor que se puede usar o no, la instrucción compuesta parece ser su única opción.
Pero __clkget()
nunca se usa como otra cosa como valor r
Algunos enlaces
- http://www.toofishes.net/blog/gcc-compound-statement-expressions/
- Abstruse #define la macro encontrada en la fuente del kernel de Linux
- macro: ¿#define a (b) ({... c;}) significa a (b) devuelve c?
- ¿Por qué necesitamos paréntesis alrededor de macro de bloque?
- ¿Están las declaraciones compuestas (bloques) rodeadas por expresiones parens en ANSI C?
Me doy cuenta de que en el modo -Wall
un standalone (1);
La declaración de expresión genera una advertencia de "declaración sin efecto", mientras que una independiente ({ 1; });
La declaración de expresión no produce advertencias.
Quizás en algún lugar del código terminen con llamadas __clk_get
independientes que ignoran el resultado. La (1)
definición resultaría en una advertencia para tales llamadas, mientras que ({ 1; })
mantendrá en silencio mientras produce el mismo efecto en otros contextos.
Una posible explicación es evitar el uso en situaciones indeseables.
Esto es útil para mejorar la portabilidad del código: si la implementación de la macro de otra macro fallara, queremos que ésta también falle.
Ejemplo: static int x = __clk_get(clk);
- No tiene sentido iniciar estáticamente con el reloj.
Con #define __clk_get(clk) (1)
, funcionará.
Con #define __clk_get(clk) ({ 1; })
, fallará.