Is it possible to define a macro called IPHONE_ONLY for conditional compilation that looks like this:
IPHONE_ONLY -(void)myMethod {
//method body
}
or
IPHONE_ONLY( -(void)myMethod {
//method body
})
Even though normally you would surround the function with #ifdef, I tested with gcc and indeed the following also works. I don't know if it is standard:
#ifdef IPHONE
# define IPHONE_ONLY(...) __VA_ARGS__
#else
# define IPHONE_ONLY(...)
#endif
IPHONE_ONLY(int func(void)
{
return 12;
})
I have never seen anyone code like that though. It is quite common to write such a function like this:
#ifdef IPHONE
int func(void)
{
return 12;
}
#endif
Your editor also would be much happier with this, since it understands functions, but not function body used as a macro parameter!
Sure you can, but I don't think that this would make your code more readable
#if on_iphone
# define IPHONE_ONLY(...) __VA_ARGS__
#else
# define IPHONE_ONLY(...)
#endif
and then you can use the macro the 2nd way you have it in your question.
But this is really ugly and against the visual expectations of anybody who is used to read proper C.
I think you are looking for ifdef:
#ifdef IPHONE_ONLY
void myMethod(){
//method body
)
#endif
#ifdef IPHONE_ONLY
# define MY_METHOD() myMethod();
void myMethod() {
......
}
#else
# define MY_METHOD()
#endif
in your c code of your project, you call MY_METHOD().
This will avoid you to call myMethod() in that way each time you need it in your code
for(i=0; i<10; i++) {
// some thing to do here
#ifdef IPHONE_ONLY
myMethod();
#endif
// other thing to do here
}
with the definition above you will call your myMethod(); in this way
for(i=0; i<10; i++) {
// some thing to do here
MY_METHOD();
// other thing to do here
}
If IPHONE_ONLY is defined then the prepocessor will change the macro MY_METHOD() by the call of the function myMethod();
If IPHONE_ONLY is not defined then the preprocessor will change the MY_METHOD() by nothing. It's like the macro call MY_METHOD() does not exist in your code. and the function void myMethod() will not be defined
Related
I want to implement unit testing using the -Wl,--wrap trick, however this doesn't work for functions within the same file. One solution is to rename the function (after it has been defined) to the wrapped one, as suggested here: https://stackoverflow.com/a/11758777/526568
I came up with the following macro to avoid having to manually define __wrap_foo:
#define UNIT_TEST_SYMBOL(x) \
typeof(x) __wrap_##x __attribute__((weak, alias(#x)))
void foo(void) {
/* function body */
}
UNIT_TEST_SYMBOL(foo);
#define foo __wrap_foo
void bar(void) {
foo();
}
I then compile with -Wl,--wrap=foo.
Is it possible to avoid having to manually define foo to __wrap_foo? Can this be somehow part of the UNIT_TEST_SYMBOL?
So I have this code:
#ifdef FEATURE
void foo(void);
#endif //#ifdef FEATURE
main {
#ifdef FEATURE
foo();
#endif //FEATURE
}
I'm just wondering if there is more elegant to write this. I was thinking about doing something like this
#ifdef FEATURE
void foo(void);
#else
static inline foo() {
}
#endif //#ifdef FEATURE
That way the compiler should just remove that bit of code out of there and keep the main code cleaner.
Just wondering if there is a better solution out there?
You can do it like this:
#ifdef FEATURE
void foo (void) { }
#else
#define foo()
#endif //#ifdef FEATURE
int main () {
foo();
return 0;
}
if there is a better solution out there?
No. And the solution is perfectly fine and doesn't need anything better.
Some prefer to drop inline specifier as it is only a hint to the compiler and just static void foo(void) {}. (But inline specifier silences -Wunused-function warning on gcc, so I'll say use it).
I was studying the Linux wireless subsystem code and noticed this code (in ieee80211_rx_handlers):
It first defines the macro:
#define CALL_RXH(rxh) \
do { \
res = rxh(rx); \
if (res != RX_CONTINUE) \
goto rxh_next; \
} while (0);
Then the macro is used to call a series of functions:
CALL_RXH(ieee80211_rx_h_check_more_data)
CALL_RXH(ieee80211_rx_h_uapsd_and_pspoll)
CALL_RXH(ieee80211_rx_h_sta_process)
CALL_RXH(ieee80211_rx_h_decrypt)
CALL_RXH(ieee80211_rx_h_defragment)
CALL_RXH(ieee80211_rx_h_michael_mic_verify)
My question is, why not just call the functions directly like:
ieee80211_rx_h_check_more_data(rx);
ieee80211_rx_h_uapsd_and_pspoll(rx);
...
Is it just for the sake of outlining the code for easy reading?
Each use of the macro expands into the if check and goto, not just a single function call.
The if tests differ only by which function is called to produce the condition. Because the code would otherwise be repetitive, they used a macro to generate the boilerplate.
They could perhaps have interspersed calls res = xyz( rx ); with a macro expanding to the if … goto part, and then the macro would not take any parameter. How much gets encapsulated into the macro is a matter of code factoring style.
The do {} while(0) Macro could be easily used in condition block.
#define FUNC1() doing A; dong B;
#define FUNC2() do { doing A; doing B; } while(0)
We could use FUNC2() in if condition code block like this:
if (true)
FUNC2();
But FUNC1() could only be used like this:
if (true) {
FUNC1()
}
Is there a macro trick to rename just the function calls without affecting the function definition, specifically for gcc/cpp:
#define get_resolution __mock_get_resolution
The above macro changes all places, but I just want this to take effect for the function call get_resolution(); without affecting the definition void get_resolution()
void get_resolution()
{
}
void display()
{
get_resolution();
}
As gcc-specific solution,
The `alias' attribute causes the declaration to be emitted as an
alias for another symbol, which must be specified. For instance,
void __f () { /* Do something. */; }
void f () __attribute__ ((weak, alias ("__f")));
No, the C preprocessor has no semantic knowledge of the structure of the C program, it just sees text tokens.
One option would be to #undef the macro before the definition and redefine it afterwards, but this is messy. Another option would be to add a macro to the definition of each function you want to mock like this:
#if DO_MOCKING
#define IMPLEMENT_MOCKABLE_FUNCTION(funcname) _real_ ## funcname
#define get_resolution _mock_get_resolution
#else
#define IMPLEMENT_MOCKABLE_FUNCTION(funcname) funcname
#endif
...
void IMPLEMENT_MOCKABLE_FUNCTION(get_resolution)()
{
...
}
Also note that identifiers beginning with two underscores, as well as identifiers beginning with an underscore followed by a capital letter, are reserved by the implementation (i.e. the compiler and standard libraries). So I've renamed the identifiers in the example above to use a single underscore and a lowercase letter.
You could do something like this:
#define get_resolution __mock_get_resolution
somewhere globally accessible (like a header you always include etc.) and then do this:
#undef get_resolution
void get_resolution()
{
}
#define get_resolution __mock_get_resolution
void display()
{
get_resolution();
}
Ugly hack, but it will save you having to write a sed(1) script.
Test case follows:
$ gcc -o test test.c
$ ./test
__mock_up
$ cat test.c
#include <stdio.h>
#define get_resolution __mock_up
int
__mock_up()
{
printf("__mock_up\n");
}
#undef get_resolution
int
get_resolution()
{
}
#define get_resolution __mock_up
int main()
{
get_resolution();
return 0;
}
$
I have a function which takes variable arguments, something like the following
int log_data (LOG_TYPE eType, ...)
{
/** some logging related stuff here **/
}
In the header file, I use something like
#ifdef LOGGING_ENABLED
int log_data (int nType, ...);
#else
#define log_data(_x_, ...)
#endif
Basically, the idea is to SWITCH debugging ON & OFF ~~~
Problem:
The above logic works perfectly fine in Linux & gcc, but errors outs during compilation in Windows VC++.
Variadic macros are relatively new, for example: this reference says that "Support for variadic macros was introduced in Visual C++ 2005." You might have an older version.
Edit: you are declaring log_data if you want debugging, and not if you don't. This means that you have the definition of the function in an #ifdef as well. As long as you're doing this, a solution would be:
int log_data (int nType, ...)
{
#ifdef LOGGING_ENABLED
/* the code to do logging */
#else
return 0; /* or whatever */
#endif
}
and in your header file, declare the function as usual:
int log_data (int nType, ...);
This has a disadvantage that the function call exists even when you're not logging, but the advantage is that it will work without preprocessor support for varargs.
Older versions of VC++ do not support variable arguments in macros.
You can use this trick to get around it:
#ifdef LOGGING_ENABLED
#define log_data log_data_impl
#else
#define log_data
#endif
// usage:
log_data(level, ...)
UPDATE - Another possible workaround:
#ifdef LOGGING_ENABLED
#define log_data(P) log_data_impl P // no braces around P!
#else
#define log_data(P)
#endif
// usage: we have to use two braces
log_data((level, ...));