2

I try to use define to replace function call, but I can't find how to replace only the call and not the declaration.

IE:

#define test(); printf("worked\n");

void test()
{
printf("how sad ?\n");
}

int main()
{
test();
}

I can't create my define after the function (project rules)

The problem is : I expected the semicolon after "test()" in the define to replaces only the call, but it replaces also the declaration.

I tried to google and nothing on that, is it really possible ? It's weird that it is not taking the literal expression.

4 Answers 4

7

A few things to note:

  • #define doesn't require braces () - only use them if you need to handle parameters
  • The syntax doesn't include a semicolon: #define test printf
  • Calling a function like printf() like this (somewhat obscured) can be risky, especially if the caller doesn't expect that their string is used as a format string. Prefer #define test(msg) printf("%s", msg)
  • After a #define test ..., the pre-processor will dumbly replace all instances of test - thus the function declaration will actually read void printf("worked\n"); { ... }

The result should be either:

#include <stdio.h>

#define test(msg) printf("%s\n", msg)

void main(void) {
    test("hello");
}

or:

#include <stdio.h>

void test(const char *msg) {
    printf("%s\n", msg);
}

void main(void) {
    test("hello");
}

If you are trying to use a #define to redirect a function call, then you must use a different symbol... for example:

#include <stdio.h>

/* Comment / uncomment this to change behaviour */
#define REDIRECT_TEST

#ifdef REDIRECT_TEST
#  define my_test(msg) printf("REDIRECTED:%s\n", msg)
#else
#  define my_test      test    
#endif

void test(const char *msg) {
    printf("%s\n", msg);
}

void main(void) {
    my_test("hello");
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer. Sadly, my project really restrict me and I can't use your solution. I will have to do it manually.
#define test(); printf("worked\n"); actually means that when you write test() it will output ; printf("worked\n"); (notice that extra semicolon)... (or am I wrong?)
1

printf have a "variadic arguments". Sometimes уou will have a problem if you wont use any solution from that q/a: "How to wrap printf() into a function or macro?"

Some tip like this, for example:

#define MY_PRINTF(...) printf(__VA_ARGS__)

or this:

#define MY_PRINTF(f_, ...) printf((f_), ##__VA_ARGS__)

Comments

0

you should have the define at a separated header file. and the define shall not include the semicolon. so your code shall look like this:

replace_test.h:

#define test() dummy_test()

test.h:

void test();

test.c:

void test()
{ your test code}

dummy.c:

void dummy_test()
{
 your dummy code here (printf("worked!"); etc.
}

program.c:

//decide which behavior you want, either include replace_test.h or test.h header
#include "replace_test.h"
//#include "test.h"

int main()
{
   test();
}

6 Comments

Can you explain why do you think the answer is completely wrong??? as far as I know, this the common way to use mocks at c with macros. having the define at a header, and using the dummy header as needed.
You did macro with name test and then function with the same name test. what?
it is OK to have a macro and a function with the same name. It would cause problem only if the file test.c or test.h have include to replace_test.h. at the using code (program.c), the user can decide whether to include the real test.h header, and really call the function test(), or to include the replace_test.h header, and have the code which call 'test()' replaced with a call to 'dummy_test()' method.
BTW, regarding mock methods I mentioned before, there is one way doing this with macros, as I mentioned, and another way doing this using function pointers, directing pointers to dummy implementations as needed.
Then explain properly.
|
0

Here is an excerpt from my unit test framework. I believe this does what you want...

void *(*old_calloc)(size_t, size_t) = calloc;
#define calloc unit_calloc
void *unit_calloc(size_t num, size_t size) {
    ...
    void* retv = old_calloc(num, size);
    ...
    return retv;
}

This allows me to redirect a call to calloc() without modifying the code that I am trying to test.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.