2010-04-20 12 views
6

En general, he ignorado el uso de macros al escribir en C, pero creo que conozco los fundamentos sobre ellas. Mientras estaba leyendo el código fuente de la lista en el núcleo de Linux, vi algo así:Expansión de macro C en el código de kernel de Linux

#define LIST_HEAD_INIT(name) { &(name), &(name) } 
#define LIST_HEAD(name) \ 
    struct list_head name = LIST_HEAD_INIT(name) 

(Se puede acceder a la parte restante del código de here.)

no entendía la función de ampersands (no creo que sean la dirección de los operandos aquí) en LIST_HEAD_INIT y, por lo tanto, el uso de LIST_HEAD_INIT en el código. Apreciaría si alguien puede iluminarme.

Respuesta

14

saber lo que realmente está sucediendo necesitamos la definición de struct list_head:

struct list_head { 
     struct list_head *next, *prev; 
}; 

Consideremos ahora las macros:

#define LIST_HEAD_INIT(name) { &(name), &(name) } 
#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name) 

Si en el código que escribo LIST_HEAD(foo) que se expandió a:

struct list_head foo = { &(foo) , &(foo)} 

que representa un vacía la lista doblemente enlazada con un nodo de encabezado donde los punteros next y prev apuntan al nodo del encabezado en sí.

Es mismo que hacer:

struct list_head foo; 
foo.next = &foo; 
foo.prev = &foo; 

Así que efectivamente estas macros proporcionan una forma para inicializar una lista doblemente enlazada.

Y sí, & se utiliza aquí como la dirección del operador.

EDIT:

Aquí está una working example

En el enlace proporcionado por usted. Usted tenía:

struct list_head test = LIST_HEAD (check); 

que es incorrecto. Debe tener:

LIST_HEAD (check); 
+0

@ unicornaddict consideré el escenario similar antes de hacer esta pregunta. Pero recibí un error cuando probé este código: http://pastebin.com/P2cCfNbQ. Traté de dar vacío, int, macro, etc ... y obtuve errores en esas condiciones también. – systemsfault

+0

@holydiver: He actualizado mi respuesta con un enlace a ** ejemplo de trabajo ** y también he señalado el error en * su * código. – codaddict

+0

gracias ahora realmente lo tengo. – systemsfault

3

Aquí están los operadores de la dirección. Las listas vinculadas en el kernel evitan los punteros nulos para denotar el final de una lista. Por lo tanto, el encabezado debe inicializarse con algún puntero válido. En esta implementación, si el puntero de "cabeza" o "cola" apunta a la dirección del encabezado de la lista, la lista se considera vacía.

1

Parece que la macro no se usa en el list.h.

Supongo que & realmente significa direcciones en el código. El struct list_head contiene dos punteros, por lo que debe ser bastante natural para la declaración struct list_head name = LIST_HEAD_INIT(name) (ver macro LIST_HEAD) para obtener un par de punteros como inicializador.

0

Eso es exactamente lo que son, los ampersands toman la dirección del parámetro y los almacenan en los campos de "encabezado" y "siguiente". No pude decirle por qué, ya que no encontré un uso real de esta macro, pero eso es lo que hace.

8

Cada vez que tenga dudas sobre qué macro está haciendo en realidad, puede pedirle a 'gcc -E' que lo expanda por usted.

En este caso, solo inicia una estructura de lista con punteros a sí mismo.

+1

+1 para la opción E idea – Dacav

+0

Wow no sabía esta opción antes. Gracias – systemsfault

+0

o cpp -v usando el preprocesador –

Cuestiones relacionadas