2014-09-23 3 views
1

현재 값을 검사하는 매크로가 유형입니다.C에서 여러 유형의 컴파일 시간을 확인 하시겠습니까?

#define CHECK_TYPE_INLINE(val, type) \ 
    ((void)(((type)0) != (0 ? (val) : ((type)0)))) 

매크로 args를 유형 검사 할 수있는 경우에 유용합니다.

하지만 여러 가지 유형을 확인하려면 어떻게해야합니까? 예를 들어 struct Foo * 또는 struct Bar *인지 확인합니다.

예,

static inline _insert_item(struct List *ls, void *item) { /* function body*/ } 

/* type-checked wrapper */ 
#define insert_item(ls, item) \ 
    (CHECK_TYPE_ANY(item, struct Foo *, struct Bar *), \ 
    _insert_item(ls, item)) 

는이 작업을 수행하는 좋은 방법이 있나요? 이것은 C11 태그 때문에

+3

당신이 당신이 예제에서 매크로를 사용 얼마나 보여줄 수 생성하는 데 사용? – imreal

+0

@imreal, good point, done – ideasman42

답변

3

, 당신은 _Generic 키워드를 통해 이에 대한 언어 지원 : 1, 2, 3이 전달 된 인수는 특정 유형의 경우 발생해야하는 것들입니다

#define CHECK(x) _Generic((x), \ 
        int : 1, \ 
        float : 2, \ 
        default : 3) 

.

Link with some good examples.

+0

값이 사용되지 않도록하려면 _Generic 앞에'(void)'를 포함하는 것이 좋습니다. (이것은 유형을 확인하는 데만 사용된다고 가정) – ideasman42

0

@ Lundin의 답변에 추가하려면 __VA_ARGS__과 함께 사용할 수 있습니다.

/* From: http://stackoverflow.com/questions/24836793/varargs-elem-macro-for-use-with-c/24837037#24837037 */ 

/* -------------------------------------------------------------------- */ 
/* varargs macros (keep first so others can use) */ 
/* --- internal helpers --- */ 
#define _VA_NARGS_GLUE(x, y) x y 
#define _VA_NARGS_RETURN_COUNT(\ 
    _1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, _10_, _11_, _12_, _13_, _14_, _15_, _16_, \ 
    _17_, _18_, _19_, _20_, _21_, _22_, _23_, _24_, _25_, _26_, _27_, _28_, _29_, _30_, _31_, _32_, \ 
    count, ...) count 
#define _VA_NARGS_EXPAND(args) _VA_NARGS_RETURN_COUNT args 
#define _VA_NARGS_COUNT_MAX32(...) _VA_NARGS_EXPAND((__VA_ARGS__, \ 
    32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, \ 
    15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)) 
#define _VA_NARGS_OVERLOAD_MACRO2(name, count) name##count 
#define _VA_NARGS_OVERLOAD_MACRO1(name, count) _VA_NARGS_OVERLOAD_MACRO2(name, count) 
#define _VA_NARGS_OVERLOAD_MACRO(name, count) _VA_NARGS_OVERLOAD_MACRO1(name, count) 
/* --- expose for re-use --- */ 
#define VA_NARGS_CALL_OVERLOAD(name, ...) \ 
    _VA_NARGS_GLUE(_VA_NARGS_OVERLOAD_MACRO(name, _VA_NARGS_COUNT_MAX32(__VA_ARGS__)), (__VA_ARGS__)) 

/* -------------------------------------------------------------------- */ 
/* CHECK_TYPE_ANY */ 

#define _VA_CHECK_TYPE_ELEM2(v, a) \ 
    ((void)_Generic((v), a: 0)) 
#define _VA_CHECK_TYPE_ELEM3(v, a, b) \ 
    ((void)_Generic((v), a: 0, b: 0)) 
#define _VA_CHECK_TYPE_ELEM4(v, a, b, c) \ 
    ((void)_Generic((v), a: 0, b: 0, c: 0)) 
#define _VA_CHECK_TYPE_ELEM5(v, a, b, c, d) \ 
    ((void)_Generic((v), a: 0, b: 0, c: 0, d: 0)) 
#define _VA_CHECK_TYPE_ELEM6(v, a, b, c, d, e) \ 
    ((void)_Generic((v), a: 0, b: 0, c: 0, d: 0, e: 0)) 
#define _VA_CHECK_TYPE_ELEM7(v, a, b, c, d, e, f) \ 
    ((void)_Generic((v), a: 0, b: 0, c: 0, d: 0, e: 0, f: 0)) 
#define _VA_CHECK_TYPE_ELEM8(v, a, b, c, d, e, f, g) \ 
    ((void)_Generic((v), a: 0, b: 0, c: 0, d: 0, e: 0, f: 0, g: 0)) 

/* For general use */ 
#define CHECK_TYPE_ANY(...) VA_NARGS_CALL_OVERLOAD(_VA_CHECK_TYPE_ELEM, __VA_ARGS__) 

사용 예 :

static inline _insert_item(struct List *ls, void *item) { /* function body*/ } 

/* type-checked wrapper */ 
#define insert_item(ls, item) \ 
    (CHECK_TYPE_ANY(item, struct Foo *, struct Bar *), \ 
    _insert_item(ls, item)) 

주, 파이썬 스크립트는 _VA_CHECK_TYPE_ELEM#

for i in range(32): 
    args = [(("" if c < 26 else "_") + chr(ord('a') + (c % 26))) for c in range(i + 1)] 
    print("#define _VA_CHECK_TYPE_ELEM%d(var, %s) \\" % (i + 2, ", ".join(args))) 
    print(" ((void)_Generic((var), %s))" % (": 0, ".join(args) + ": 0"))