在编译时为

时间:2015-12-18 20:36:42

标签: c gcc struct c-preprocessor

有一个库,它接受在编译时定义行格式的结构。不同的用户具有不同的结构变体。

一个例子:

typedef struct { INT16U a, INT32S b } logrow_t;

在运行时,我想迭代这个结构并打印每个元素及其类型。

首先想到的解决方案是构建一个表:

typedef struct { char var_name[16], char var_type[16], int bytelen } logrow_desc_t;

logrow_desc_t descriptions[] = { { "a", "INT16U", 2 }, { "b", "INT32S", 4 } };

是否有更好的解决方案允许库的任何用户指定不同的行结构?有没有办法利用预处理器/编译器在编译时构建描述表?

1 个答案:

答案 0 :(得分:0)

  

有没有办法利用预处理器/编译器来构建   编译时的描述表?

如果您和您的用户不介意在宏中指定行格式(让我们说LOGROW)而不是直接在logrow_t的定义中指定行格式,请参阅此ppnarg.h中描述的方法的变体可以使用{3}} 我将通用的,可重用的部分放在文件/* * The PP_NARG macro evaluates to the number of arguments that have been * passed to it. * Laurent Deniau, "__VA_NARG__," 17 January 2006, <comp.std.c> (29 November 2007). */ #define PP_NARG(...) PP_NARG_(__VA_ARGS__,PP_RSEQ_N()) #define PP_NARG_(...) PP_ARG_N(__VA_ARGS__) #define PP_ARG_N( \ _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,_33,_34,_35,_36,_37,_38,_39,_40, \ _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ _61,_62,_63,N,...) N #define PP_RSEQ_N() \ 63,62,61,60, \ 59,58,57,56,55,54,53,52,51,50, \ 49,48,47,46,45,44,43,42,41,40, \ 39,38,37,36,35,34,33,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 /* need extra level to force extra eval */ #define Paste(a,b) a ## b #define XPASTE(a,b) Paste(a,b) /* APPLYXn variadic X-Macro by M Joshua Ryan */ /* Free for all uses. Don't be a jerk. */ /* I got bored after typing 15 of these. */ /* You could keep going upto 64 (PPNARG's limit). */ #define APPLYX1(a) X(a) #define APPLYX2(a,b) X(a) X(b) #define APPLYX3(a,b,c) X(a) X(b) X(c) #define APPLYX4(a,b,c,d) X(a) X(b) X(c) X(d) #define APPLYX5(a,b,c,d,e) X(a) X(b) X(c) X(d) X(e) #define APPLYX6(a,b,c,d,e,f) X(a) X(b) X(c) X(d) X(e) X(f) #define APPLYX7(a,b,c,d,e,f,g) \ X(a) X(b) X(c) X(d) X(e) X(f) X(g) #define APPLYX8(a,b,c,d,e,f,g,h) \ X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) #define APPLYX9(a,b,c,d,e,f,g,h,i) \ X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) #define APPLYX10(a,b,c,d,e,f,g,h,i,j) \ X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) #define APPLYX11(a,b,c,d,e,f,g,h,i,j,k) \ X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) X(k) #define APPLYX12(a,b,c,d,e,f,g,h,i,j,k,l) \ X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) X(k) X(l) #define APPLYX13(a,b,c,d,e,f,g,h,i,j,k,l,m) \ X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) X(k) X(l) X(m) #define APPLYX14(a,b,c,d,e,f,g,h,i,j,k,l,m,n) \ X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) X(k) X(l) X(m) X(n) #define APPLYX15(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o) \ X(a) X(b) X(c) X(d) X(e) X(f) X(g) X(h) X(i) X(j) X(k) X(l) X(m) X(n) X(o) #define APPLYX_(M, ...) M(__VA_ARGS__) #define APPLYXn(...) APPLYX_(XPASTE(APPLYX, PP_NARG(__VA_ARGS__)), __VA_ARGS__) //#define ZIP2(a,b) /* to be defined by application */ #define ZIP4(a,b,c,d) ZIP2(a,b) ZIP2(c,d) #define ZIP6(a,b,c,d,e,f) ZIP4(a,b,c,d) ZIP2(e,f) #define ZIP8(a,b,c,d,e,f,g,h) ZIP6(a,b,c,d,e,f) ZIP2(g,h) #define ZIP10(a,b,c,d,e,f,g,h,i,j) ZIP8(a,b,c,d,e,f,g,h) ZIP2(i,j) #define ZIP12(a,b,c,d,e,f,g,h,i,j,k,l) ZIP10(a,b,c,d,e,f,g,h,i,j) ZIP2(k,l) // define more of those ZIPxx() if more arguments are needed #define ZIP(...) APPLYX_(XPASTE(ZIP, PP_NARG(__VA_ARGS__)), __VA_ARGS__) 中:

// only this line is to be defined by the users:
#define LOGROW  INT16U, a, INT32S, b

// the following defines `logrow_t` and `descriptions` according to the above:
#include <stddef.h>
#include "ppnarg.h"

#define ZIP2(a, b)  a b;
typedef struct { ZIP(LOGROW) } logrow_t;
#undef  ZIP2
typedef struct { char *name, *type; size_t size; } logrow_desc_t;
#define ZIP2(a, b)  { #b, #a, sizeof (a) },
logrow_desc_t descriptions[] = { ZIP(LOGROW) };
#undef  ZIP2

在您的应用程序中,可以这样使用:

SELECT p.id,p.title
FROM product_products p 
LEFT JOIN product_attribute_values v ON v.product_id = p.id
LEFT JOIN product_attribute_options o ON o.id = v.option_id
WHERE (p.id = 82 OR p.parent_id = 82)
  AND (o.id IN (25, 3))
GROUP BY p.id,p.title
HAVING COUNT(DISTINCT o.id) = 2