I write an example to show my problem, here it is to use nested macros to make calls to check the number is positive and odd. I know this is redundant to use this call, but as I said previously, it just show that if using macro in nested way, there is some problem:
#include <stdio.h>
#include <stdlib.h>
#define num_is_positive_odd(num) \
({ \
int __rc = 0; \
int __num = (num); \
\
printf("%s:%d: check linenum\n", __func__, __LINE__); \
if (num_is_positive(__num) && num_is_odd(__num)) \
__rc = 1; \
__rc; \
})
#define num_is_positive(num) \
({ \
int __rc = 0; \
int __num = (num); \
\
if (__num > 0) { \
printf("%s: number %d is positive\n", \
__func__, __num); \
__rc = 1; \
} \
__rc; \
})
#define num_is_odd(num) \
({ \
int __rc = 0; \
int __num = (num); \
\
if (__num / 2) { \
printf("%s: number %d is odd\n", \
__func__, __num); \
__rc = 1; \
} \
__rc; \
})
int main()
{
int num = 4;
if (num_is_positive_odd(num++))
printf("%s: number %d is positive odd\n", __func__, num);
exit(0);
}
When compile it using command: gcc -Wunused-variable chk_comps.c
it shows error:
chk_comps.c: In function ‘main’:
chk_comps.c:7:9: warning: unused variable ‘__num’ [-Wunused-variable]
int __num = (num); \
^
chk_comps.c:47:9: note: in expansion of macro ‘num_is_positive_odd’
if (num_is_positive_odd(num++))
^
`
Could somebody help explain why and how to fix it? thanks.
This is using a GCC extension called statement expressions — so the rules are specific to GCC (and probably Clang emulating GCC).
If you run gcc -E, you can see that the raw output for main() (with the void added by me) is:
# 41 "gccm43.c"
int main(void)
{
int num = 4;
if (({ int __rc = 0; int __num = (num++); printf("%s:%d: check linenum\n", __func__, 45); if (({ int __rc = 0; int __num = (__num); if (__num > 0) { printf("%s: number %d is positive\n", __func__, __num); __rc = 1; } __rc; }) && ({ int __rc = 0; int __num = (__num); if (__num / 2) { printf("%s: number %d is odd\n", __func__, __num); __rc = 1; } __rc; })) __rc = 1; __rc; }))
printf("%s: number %d is positive odd\n", __func__, num);
return 0;
}
which, when manually formatted (a variation on the theme of 'purgatory'), might look like:
# 41 "gccm43.c"
int main(void)
{
int num = 4;
if (({ int __rc = 0;
int __num = (num++);
printf("%s:%d: check linenum\n", __func__, 45);
if (({ int __rc = 0;
int __num = (__num);
if (__num > 0)
{
printf("%s: number %d is positive\n", __func__, __num);
__rc = 1;
}
__rc;
}) &&
({ int __rc = 0;
int __num = (__num);
if (__num / 2)
{
printf("%s: number %d is odd\n", __func__, __num);
__rc = 1;
}
__rc;
}
))
__rc = 1;
__rc;
}
))
printf("%s: number %d is positive odd\n", __func__, num);
return 0;
}
The lines int __num = (__num); are problematic; you are initializing the variable with itself, which doesn't really do a good job (the value is indeterminate before and after the initialization). You also used (__num / 2) to determine whether __num is odd, which is an odd way to detect oddness; you should use (__num % 2).
It is also now evident why the compiler warns that (one of the) __num (variables) is not used. The outer declaration assigns num++ to __num, but the initialized variable is never used because the inner occurrences of int __num = (__num); refer to themselves and not to the outer __num, so it isn't used.
You'd do better with static inline functions — something like this:
#include <stdio.h>
#include <stdlib.h>
static inline int num_is_positive(int num)
{
int rc = 0;
if (num > 0)
{
printf("%s: number %d is positive\n", __func__, num);
rc = 1;
}
return rc;
}
static inline int num_is_odd(int num)
{
int rc = 0;
if (num % 2) // BUG fixed
{
printf("%s: number %d is odd\n", __func__, num);
rc = 1;
}
return rc;
}
static inline int num_is_positive_odd(int num)
{
int rc = 0;
printf("%s:%d: check linenum\n", __func__, __LINE__);
if (num_is_positive(num) && num_is_odd(num))
rc = 1;
return rc;
}
int main(void)
{
int num = 4;
if (num_is_positive_odd(num++))
printf("%s: number %d is positive odd\n", __func__, num);
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With