2010-06-08 13 views
1

Étant donné le code suivant (il s'agit d'une macro qui génère du code pour une structure de données de liste, en fonction du type contenu).Problème de macro C: redéfinition des fonctions/structure

list.h

#ifndef _LIST_H 
#define _LIST_H 

#ifdef __cplusplus 
extern "C" { 
#endif 

#define LIST_TEMPLATE_INIT(type) \ 
    typedef struct __list_s_##type { \ 
     struct __list_s_##type *next; \ 
     type value; \ 
    } __list_##type; \ 
\ 
    __list_##type * __list_##type##_malloc(type value){ \ 
     __list_##type * list = NULL; \ 
     list = malloc(sizeof(*list)); \ 
     list->value = value; \ 
     return list; \ 
    }\ 
\ 
    void __list_##type##_free(__list_##type *list){\ 
     __list_##type * back = list;\ 
     while(list=list->next){\ 
      free(back);\ 
      back = list;\ 
     }\ 
    } 
#define LIST_TYPE(type) __list_##type 
#define LIST_MALLOC(type,value) __list_##type##_malloc(value) 
#define LIST_FREE(type,list) __list_##type##_free(list) 
#define LIST_DATA(list) (list->value) 

#ifdef __cplusplus 
} 
#endif 

#endif /* _LIST_H */ 

Et voici comment fonctionne le code ci-dessus:

#include <stdio.h> 
#include <stdlib.h> 
#include "list.h" 

/* 
* 
*/ 
LIST_TEMPLATE_INIT(int) 
int main(int argc, char** argv) 
{ 
LIST_TYPE(int)* list = NULL; 
list = LIST_MALLOC(int, 5); 
printf("%d",LIST_DATA(list)); 
LIST_FREE(int,list); 
return (0); 
} 

Ma question, est-il possible d'être en quelque sorte capable d'appeler: LIST_TEMPLATE_INIT(int), autant de fois comme je le veux, de manière décentralisée?

La question actuelle avec ce droit est maintenant appeler LIST_TEMPLATE_INIT(int) dans une autre erreur de compilation soulèvent des fichiers (en raison de la redéfinition de la fonction):

Exemple d'erreur:

error: redefinition of ‘struct __list_s_int’ 
error: redefinition of ‘struct __list_s_int’ 
error: conflicting types for ‘__list_int’ 
note: previous declaration of ‘__list_int’ was here 
error: conflicting types for ‘__list_int_malloc’ 
note: previous definition of ‘__list_int_malloc’ was here 
error: conflicting types for ‘__list_int_free’ 
note: previous definition of ‘__list_int_free’ was here 
+0

extern "C" est la définition d'emballage redondant macro –

+0

été générée par l'IDE. Merci pour votre commentaire, je vais enquêter! –

Répondre

5

Je suggère la création de macros différentes pour déclarer et définir la structure de la liste, puis en utilisant les fichiers d'en-tête et de source séparés pour chacun:

list.h:

#ifndef _LIST_H  
#define _LIST_H  

#define LIST_TEMPLATE_DECLARE(type)     \ 
    struct __list_##type;        \ 
    typedef struct __list_##type __list_##type;  \ 
    struct __list_##type {       \ 
     struct __list_##type * next;     \ 
     type value;         \ 
    };            \ 
                 \ 
__list_##type * __list_##type##_malloc(type value); \ 
void __list_##type##_free(__list_##type * list); 

#define LIST_TEMPLATE_DEFINE(type)     \ 
__list_##type * __list_##type##_malloc(type value) { \ 
    __list_##type * list = NULL;      \ 
    list = malloc(sizeof(*list));      \ 
    list->value = value;        \ 
    return list;          \ 
}              \ 
void __list_##type##_free(__list_##type * list) {  \ 
    __list_##type * back = list;      \ 
    while(list=list->next){       \ 
     free(back);         \ 
     back = list;         \ 
    }             \ 
} 

#define LIST_TYPE(type) __list_##type  
#define LIST_MALLOC(type,value) __list_##type##_malloc(value)  
#define LIST_FREE(type,list) __list_##type##_free(list)  
#define LIST_DATA(list) (list->value)  

#endif /* _LIST_H */  

int_list.h:

#ifndef INT_LIST_H_ 
#define INT_LIST_H_ 

#include "list.h" 
LIST_TEMPLATE_DECLARE(int) 

#endif /* INT_LIST_H_ */ 

int_list.c:

#include "int_list.h" 

LIST_TEMPLATE_DEFINE(int) 

other.c:

#include "int_list.h" 

int some_function(int argc, char** argv) 
{ 
    LIST_TYPE(int)* list = NULL; 
    list = LIST_MALLOC(int, 5); 
    printf("%d",LIST_DATA(list)); 
    LIST_FREE(int,list); 
    return (0); 
} 
+0

extern C est redondant enveloppant la définition de macro - doit être déplacé à init_list.h ou ajouté à la macro elle-même de façon appropriée –

+0

Bon appel. Je vais l'enlever. –

0

Faites le type struct sous-jacente anonyme. Cela vous permettra de définir autant que votre coeur désire:

#define LIST_TEMPLATE_INIT(type) \ 
    typedef struct { \ 
     struct __list_s_##type *next; \ 
     type value; \ 
    } __list_##type; \ 
+0

Pouvez-vous être plus précis s'il vous plaît? Êtes-vous sûr que ça va marcher? Le problème ne concerne pas seulement la structure, mais aussi les fonctions. –

+2

Cela ne fonctionnera pas, puisque le pointeur 'next' doit être du même type que la structure de la liste. –