Variadische Makros: Anzahl der Argumente bestimmen

05/10/2007 - 16:06 von Felix von Leitner | Report spam
Ich hàtte gerne eine variadische Funktion, die für alle ihre Argumente
free() aufruft. Die Idee ist sowas wie:

mfree(ptr1,ptr2,ptr3,ptr4->data,ptr4);

Problem: die Funktion selbst weiß nicht, wie viele Argumente man ihr
übergibt. Daher ist der Standardweg für sowas, ein variadisches Makro
drum herum zu deklarieren, das am Ende einen magischen Terminator-Wert
anhàngt. Beispiel:

#define mputs(f,...) _mputs(f,__VA_ARGS__,NULL)

void _mputs(FILE* f,...) {
va_list a;
const char* s;
va_start(a,b);
while ((s=va_arg(a,const char*)))
fputs(s,f);
va_end(a);
}

Das ist schon mal grundsàtzlich scheiße, weil es in-band signalling ist.
Für puts kann man noch sagen, dass NULL kein gültiger normaler
Übergabewert ist, aber bei free wàre das halt nicht der Fall.

Ich hàtte daher gerne eine Methode, wie ich statt am Ende einen
besondere Terminator am Anfang die Anzahl der folgenden Argumente
übergeben kann. Leider scheint das in C99 nicht zu gehen, und ich habe
nicht mal eine GNU Extension dafür gefunden. Das ## Zeugs bei GNU und
variadischen Makros sah vielversprechend aus, aber hàtte nur mit
rekursiver Makroauflösung Erfolgschancen, und die müßte man ja auch erst
mal einschalten. Der Code soll mit Default-Compiler-Einstellungen tun.

Ja, man kann sich auch bei free() einen Wert ausdenken, der normal nie
vorkommen sollte, z.B. einen Wert mit falschem Alignment, z.B.
0xffffffff. Aber das ist halt immer noch widerliches
in-band-signalling.

Hat jemand eine Idee?

Felix
 

Lesen sie die antworten

#1 Felix von Leitner
05/10/2007 - 16:30 | Warnen spam
Thus spake Felix von Leitner ():
Hat jemand eine Idee?



Stellt sich raus, dass es doch eine Lösung dafür gibt:

http://groups.google.com/group/comp...64319b1ee5

Ich zitiere mal fürs Archiv:


/* The PP_NARG macro returns the number of arguments that have been
* passed to it.
*/

#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

/* Some test cases */
PP_NARG(A) -> 1
PP_NARG(A,B) -> 2
PP_NARG(A,B,C) -> 3
PP_NARG(A,B,C,D) -> 4
PP_NARG(A,B,C,D,E) -> 5
PP_NARG(1,2,3,4,5,6,7,8,9,0,
1,2,3,4,5,6,7,8,9,0,
1,2,3,4,5,6,7,8,9,0,
1,2,3,4,5,6,7,8,9,0,
1,2,3,4,5,6,7,8,9,0,
1,2,3,4,5,6,7,8,9,0,
1,2,3) -> 63

Note: using PP_NARG() without arguments would violate 6.10.3p4 of ISO C99.

Ähnliche fragen