0
#define SEND_VALUE(num, point1, point2, point3...) \
{ \
  char number[6]; \
  char p1[6];\
  char p2[6];\
  char p3[6];\
  if(num == ONE) {sprintf(number, "ONE");}\
  if(num == TWO) {sprintf(number, "TWO");}\
  if(num == THREE) {sprintf(number, "THREE");}\
  if(point1 == ONE) {sprintf(p1, "ONE");}\
  if(point1 == TWO) {sprintf(p1, "TWO");}\
  if(point1 == THREE) {sprintf(p1, "THREE");}\
  if(point2 == ONE) {sprintf(p2, "ONE");}\
  if(point2 == TWO) {sprintf(p2, "TWO");}\
  if(point2 == THREE) {sprintf(p2, "THREE");\
  if(point3 == ONE) {sprintf(p3, "ONE");}\
  if(point3 == TWO) {sprintf(p3, "TWO");}\
  if(point3 == THREE) {sprintf(p3, "THREE");\
  fprintf(fp,"%s:%s:%s:%s:\n",number, p1,p2,p3);\
  fflush(fp); \
  fprintf(fp,fmt,##__VA_ARGS__);\
  fflush(fp); \
  fprintf(fp,"\n");\
  fflush(fp); \
}

As of now, this macro doesn't require to be variadic. But for future use, I want it to be variadic. I don't know how to write/define the argument list in the variadic macro and how to use them. As in the above eg, p1, p2 should be set and printed.

I am calling this macro like this:

SEND_VALUE(ONE, ONE, ONE, ONE);

Could someone please help in achieving this the variadic way?

a3f
  • 8,517
  • 1
  • 41
  • 46
aod
  • 77
  • 1
  • 2
  • 7

1 Answers1

1

Assuming you also get fmt as macro parameter, here's a much shortened version of your macro:

#define SEND_VALUE(num, point1, point2, point3, ...) \
do { \
  fprintf(fp,#num":"#point1":"#point2":"#point3":\n");\
  fflush(fp); \
  fprintf(fp,__VA_ARGS__);\
  fflush(fp); \
  fprintf(fp,"\n");\
  fflush(fp); \
} while(0)

If you want to be explicit with the format, you can also do:

#define SEND_VALUE(num, point1, point2, point3, fmt, ...) \
do { \
  fprintf(fp,#num":"#point1":"#point2":"#point3":\n");\
  fflush(fp); \
  fprintf(fp,fmt,##__VA_ARGS__);\
  fflush(fp); \
  fprintf(fp,"\n");\
  fflush(fp); \
} while(0)

but you should note that ,##__VA_ARGS__ is a gcc extension.

A couple of notes:

  • Use do { } while(0) for macros that expand to code blocks to be fool-proof; they can be put as a single statement in an if/while/etc block and they can also accept ; with no run-time overhead.
  • Use #param to get a string whose value is the parameter name. In your example SEND_VALUE(ONE, ONE, ONE, ONE), #num would be "ONE".
  • In C "some"" string" is equivalent to "some string".
  • It would be better if you pass fp as a parameter to the macro too.

Edit: in the end, your macro could be used like this:

SEND_VALUE(ONE, ONE, ONE, ONE, "");
SEND_VALUE(ONE, TWO, ONE, THREE, "%d", 10);
SEND_VALUE(THREE, TWO, ONE, TWO, "format string! %s %s", "param1", "param2");
Shahbaz
  • 46,337
  • 19
  • 116
  • 182
  • I'm not sure what fmt is. Got the code from somewhere else and tried to modify. fmt is a keyword or something? Or just a receiving variable like point1, point2? And what does fprintf(fp,fmt,##__VA_ARGS__); do? – aod Jan 27 '14 at 10:53
  • 1
    @aod, `fmt` is supposed to be a format string. So `fprintf(fp,fmt,##__VA_ARGS__)` is expected to expand to something like `fprintf(fp, "%d %s", x, str)` (assuming imaginary parameters `"%d %d"`, `x`, `str`). If you don't understand what `fprintf` does, see the [man page](http://linux.die.net/man/3/fprintf). – Shahbaz Jan 27 '14 at 11:00