2010-06-08 62 views
1

給定以下代碼(它是一個基於所包含的類型爲列表數據結構生成代碼的宏)。C宏問題:重新定義函數/結構

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 */ 

這裏是上面的代碼是如何工作的:

#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); 
} 

我的問題,是它可能以某種方式能夠撥打電話:LIST_TEMPLATE_INIT(int),多次如我所願,以分散的方式?

當前的問題與現在這個權利是在另一個文件中加註編譯錯誤調用LIST_TEMPLATE_INIT(int)(因爲功能重新定義):錯誤的

例子:

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

外部的 「C」 是宏定義 – 2010-06-08 22:07:53

+0

是由IDE生成的冗餘包裝。感謝您的評論,我會調查! – 2010-06-08 22:17:21

回答

5

我建議建立不同的宏聲明和定義的表結構,然後使用每個單獨的頭文件和源文件:

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是多餘的包裝宏定義 - 應該被移到init_list.h或者被恰當地添加到宏本身 – 2010-06-08 22:09:25

+0

好的調用。我會刪除它。 – 2010-06-08 22:29:56

0

使底層結構類型匿名。這將允許您定義多達你的心臟的慾望:

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

你可以請更具體嗎?你確定要去工作嗎?問題不僅在於結構,而且在於功能。 – 2010-06-08 21:34:13

+2

這將不起作用,因爲'next'指針必須與列表結構的類型相同。 – 2010-06-08 21:41:55