5

I have a function which returns an integer value. Now I want to write a macro which call this function, gets the return value and prepends a string to it and return the resultant string.

I have tried this:

#define TEST(x)        is_enabled(x)

I call this macro in the main function as:

int ret = 0;
ret = TEST(2);
printf("PORT-%d\n", ret);

This works perfectly. However I want the macro to return the string PORT-x, where, x is the return value of the called function. How can I do this?

EDIT :

I also tried writing it into multiple lines as:

#define TEST(x)\
{\
    is_enabled(x);\
}

And called it in the main function as:

printf("PORT-%d\n", TEST(2));

But this gives a compile time error:

error: expected expression before â{â token
iqstatic
  • 2,322
  • 3
  • 21
  • 39
  • It can be done by writing a macro which "calls" `sprintf`, but you will need to allocate a buffer and pass it to that macro. The question is, why do you want this to begin with? Because it feels like you're trying to solve something in the wrong way. – barak manos Nov 25 '14 at 07:12
  • Why can't you use `strcat`? Why is a macro required? – Gopi Nov 25 '14 at 07:13
  • You should definitely write a function for this... – Antzi Nov 25 '14 at 07:13
  • @Gopi I did not want to change the underlying function to return a string so I came up with an idea to modify the output of this function using a Macro. Is it so difficult? – iqstatic Nov 25 '14 at 07:16

2 Answers2

5

Use a function, not a macro. There is no good reason to use a macro here.

You can solve it by using sprintf(3), in conjonction with malloc or a buffer. See Creating C formatted strings (not printing them) or man pages for details.

About your edit: You don't need to use braces {} in a macro, and they are causing your error as preprocessing would translate it to something like

printf("format%d", {
  is_enabled(x);
}); 

To better understand macros, run gcc or clang with -E flag, or try to read this article: http://en.wikipedia.org/wiki/C_preprocessor

Community
  • 1
  • 1
Antzi
  • 12,831
  • 7
  • 48
  • 74
2

That's a bit of a pain since you need to ensure there's storage for the string. In all honesty, macros nowadays could be reserved for conditional compilation only.

Constants are better done with enumerated types, and macro functions are generally better as inline functions (with the knowledge that inline is a suggestion to the compiler, not a demand).

If you insist on using a macro, the storage could be done with static storage though that has problems with threads if you're using them, and delayed/multiple use of the returned string.

You could also dynamically allocate the string but then you have to free it when done, and handle out-of-memory conditions.

Perhaps the easiest way is to demand the macro user provide their own storage, along the lines of:

#include <stdio.h>

#define TEST2_STR(b,p) (sprintf(b,"PORT-%d",p),b)

int main (void) {
    char buff[20];
    puts (TEST2_STR(buff, 42));

    return 0;
}

which outputs:

PORT-42

In case the macro seems a little confusing, it makes use of the comma operator, in which the expression (a, b) evaluates both a and b, and has a result of b.

In this case, it evaluates the sprintf (which populates the buffer) then "returns" the buffer. And, even if you think you've never seen that before, you're probably wrong:

for (i = 0, j = 9; i < 10; i++, j--)
    xyzzy[i] = plugh[j];

Despite most people thinking that's a feature of for, it's very much a different construct that can be used in many different places:

int i, j, k;
i = 7, j = 4, k = 42;

while (puts("Hello, world"),sleep(1),1);

(and so on).

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953