So my Visual studio is declaring both tag1 and tag2 as undefined, but they are cleary defined, can't i define one based on the other?
#define push 99
#define last_instruction push
#ifdef DEBUG
#define new_instr (1+last_instruction) //should be 100
#undef last_instruction
#define last_instruction new_instr //redifine to 100 if debug
#endif
I have some cases with tag2 and it says that the definition must be const, but it is constant it is 1+99, any help would be appreciated.
Thanks!
BA
First of all, you can't define the same macro twice. If you need to replace a macro, you first have to #undef it:
#define tag1 99
#ifdef DEBUG
#define tag2 (1+tag1)
#undef tag1
#define tag1 tag2
#endif
But this will not solve the problem. Macros are not variables, you can't use them to store values to re-use at a later point. They are text replacement, so they sort of exist in parallel.
So the new definition #define tag1 tag2 expands to 1+tag1. But at this point, there is nothing called tag1, because we just undefined it and we are not yet done re-defining it.
Ponder this too much and you'll turn crazy :) So just forget about that whole thing, what you really want to do is this:
#define tag1_val 99
#define tag1 tag1_val
#ifdef DEBUG
#undef tag1
#define tag1 (tag1_val+1)
#endif
If all you want is a few symbolic names for integer constants, you could define them in an enum like this:
enum {
push = 99,
#ifdef DEBUG
new_instr,
#endif
last_plus_1,
last_instr = last_plus_1 - 1
};
new_instr will be 100 (if DEBUG defined), last_plus_1 will be either 101 (if DEBUG defined) or 100 (if DEBUG undefined), and last_instr will be one less than last_plus_1.
Based on the answers provide I came up with a solution that although not perfect do best suit my case.
This implementation can be done in two forms:
Less changes in the future (only change 'last'):
#define push 99
#define last push
#ifdef DEBUG
#define new_instr (1+last)
#define last_instruction new_instr
#else
#define last_instruction last
#endif
OR
Clear Code but repeat 'push' in two places
#define push 99
#ifdef DEBUG
#define new_instr (1+push)
#define last_instruction new_instr
#else
#define last_instruction push
#endif
Thanks for the help.
Related
Before including a header file, I want to change a macro, like this:
#define MY_MACRO STATE_0
...
#undef MY_MACRO
#define MY_MACRO STATE_1
#include "my_header.h"
However, I'd like to change the macro back to its previous value after including the header, like this:
#define MY_MACRO STATE_0
...
#undef MY_MACRO
#define MY_MACRO STATE_1
#include "my_header.h"
#define MY_MACRO [previous value] // reassigns MY_MACRO to STATE_0
MY_MACRO can store one of several (so far, just two) states.
I have two possible solutions, but none of them are as simple as I want. The first one is to create a temporary macro storing the previous value of MY_MACRO. However, using #define OLD_MACRO MY_MACRO does not work, since OLD_MACRO will be replaced by MY_MACRO, so it will change when MY_MACRO changes. What I instead did, was to define OLD_MACRO like this:
#if MY_MACRO == STATE_0
#define OLD_MACRO STATE_0
#elif MY_MACRO == STATE_1
#define OLD_MACRO STATE_1
#else
#error Invalid state
#endif
After including the header, I can write this:
#if OLD_MACRO == STATE_0
#define MY_MACRO STATE_0
#elif OLD_MACRO == STATE_1
#define MY_MACRO STATE_1
#else
#error Invalid state
#endif
#undef OLD_MACRO
This approach requires a lot of code, and if I ever need more possible states for MY_MACRO, I have to add code in two additional places. I could use a constant variable rather than a macro to represent OLD_MACRO and redefine MY_MACRO as that variable, but then MY_MACRO would have to be evaluated at run-time since it's an alias for a variable, which I don't want. Another possible better solution was to use another macro in my_header.h if it exists, but use the default macro if it doesn't. In that case, my_header.h would look something like this:
#ifndef MY_HEADER_MY_MACRO
#define MY_HEADER_MY_MACRO MY_MACRO
#endif
In that case, I would use MY_HEADER_MY_MACRO rather than MY_MACRO in my_header.h, and the source file including my_header.h would look like this:
#define MY_MACRO STATE_0
...
#define MY_HEADER_MY_MACRO STATE_1
#include "my_header.h"
#undef MY_HEADER_MY_MACRO
However, MY_MACRO is used in a lot of different files, and I think it's a little weird and inconsistent to use another macro in one specific file because of how it's included somewhere else. Is there a better way?
I am trying to implement VERSION macro for my program, that is to be changed under certain circumstances.
macro VERSION is defined via Makefile (git info is put there) and is a string.
Now I have a set of #define'd switches and I want VERSION to reflect which of them are on. This looks now like the follows (main.h):
#define COMPLEX_DEPOSITION // This is switch. later in code it is used in #ifdef...#endif construction.
#ifdef COMPLEX_DEPOSITION
#define CD "_COMP_DEP" // this is the string I want to put in the end of VERSION
#define VERSION_ VERSION CD
#undef VERSION // this is to suppress 'macro redefinition' warning
#define VERSION VERSION_
#undef VERSION_
#endif
Well, I get a lot of errors, most of which make me think that C preprocessor works with lines in file in random order:(
Later I have an even more complex thing that is intended to make VERSION -> VERSION_WLT_GAP_2
#define WIRESLIFETIMES
#ifdef WIRESLIFETIMES
#define GAP 2
#define VERSION_ (VERSION ## "_WLT_GAP_" ## #GAP)
#define VERSION VERSION_
#undef VERSION_
#endif
and I got no idea what to do and if this is even possible
String literals concatenate naturally when placed next to each other
"foo" "bar" is the same as "foobar".
As for the second example, you probably want:
#define CAT_(A,B) A##B
#define CAT(A,B) CAT_(A,B)
#define GAP 2
#define VERSION CAT(VERSION_WLT_GAP_ , GAP)
VERSION //expands to VERSION_WLT_GAP_2
I recommend playing with gcc -E/clang -E a bit, to learn how macros work,
before trying to compose anything complex with them.
Well, the answer seems to be the following:
// https://stackoverflow.com/questions/5256313/c-c-macro-string-concatenation
// Concatenate preprocessor tokens A and B without expanding macro definitions (however, if invoked from a macro, macro arguments are expanded).
#define PPCAT_NX(A, B) A ## B
// Concatenate preprocessor tokens A and B after macro-expanding them.
#define PPCAT(A, B) PPCAT_NX(A, B)
// Turn A into a string literal without expanding macro definitions (however, if invoked from a macro, macro arguments are expanded).
#define STRINGIZE_NX(A) #A
// Turn A into a string literal after macro-expanding it.
#define STR(A) STRINGIZE_NX(A)
#define COMPLEX_DEPOSITION
#ifdef COMPLEX_DEPOSITION
#define CD "_COMPDEP"
#else
#define CD ""
#endif
#define WIRESLIFETIMES
#ifdef WIRESLIFETIMES
#define GAP 2
#define WLT STR(PPCAT(_WLT:G, GAP))
#define DISABLE_METROPOLIS
#else
#define WLT ""
#endif
#define VERSION VERSIONX CD WLT
which produces V008.1-11-g68a9c89cb4-dirty_COMPDEP_WLT:G2 and I am happy with it.
Must be noted that I changed -DVERSION=... to -DVERSIONX=... inside Makefile
#include <stdio.h>
#define LOG_D(x) { printf("D:"); printf(x);}
#define LOG_E(x) { printf("E:"); printf(x);}
void test(void)
{
LOG_D("ALL is well " );
}
I have a very huge code it has different levels of log, like above code.
In the final tested library I just need only one error logs in order to reduce the code size .
so I want something like this
#define ENABLE_DEBUG_LOG 0
#define ENABLE_ERROR_LOG 1
#define LOG_D(x) {#if(ENABLE_DEBUG_LOG==1) printf("D:"); printf(x); #endif}
#define LOG_E(x) {#if(ENABLE_ERROR_LOG==1) printf("E:"); printf(x);#endif}
I added this #if(ENABLE_DEBUG_LOG==1) just for explaining, I need some solution which can compile.
Another option - you can just comment / uncomment ENABLE_DEBUG_LOG and ENABLE_ERROR_LOG to disable / enable corresponding log level.
// #define ENABLE_DEBUG_LOG // disable DEBUG_LOG
#define ENABLE_ERROR_LOG // enable ERROR_LOG
#ifdef ENABLE_DEBUG_LOG
#define LOG_D(x) { printf("D:"); printf(x);}
#else
#define LOG_D(x) // nothing
#endif
#ifdef ENABLE_ERROR_LOG
#define LOG_E(x) { printf("E:"); printf(x);}
#else
#define LOG_E(x) // nothing
#endif
You cannot nest preprocessor directives. But you can make two versions of your macro and define them in exclusive parts of an #if or #ifdef:
#define ENABLE_DEBUG_LOG 0
#if ENABLE_DEBUG_LOG != 0
#define LOG_D(...) printf("D: " __VA_ARGS__)
#else
#define LOG_D(...) // Do nothing
#endif
Here, the disabled version just "eats" the LOG_D macro and doesn't do anything. (Note that undefined macros are treated as the value 0 in #if conditionals.)
You should be able to do something like this:
#if ENABLE_DEBUG_LOG == 1
# define LOG_D(x) { printf("D:"); printf(x);}
#else
# define LOG_D(x)
#end
That way the debug log statements will just disappear if ENABLE_DEBUG_LOG is undefined or has a different value.
Regarding the other answers, it is not good idea to define the macros completely empty when they are not enabled, as this would go wrong when error logging is enabled:
if (some_error)
LOG_E("Oops...");
do_something();
If LOG_E(x) expands to nothing, then do_something() would only be called if some_error is true, which is probably not what you want!
So you could define the "do nothing" variant of LOG_E(x) like this:
#define LOG_E(x) { }
Rather than starting and ending with braces, I tend to use the do { blah; } while (0) construct as it forces you to put a semicolon on the end when you use it. Something like this:
#if ENABLE_ERROR_LOG
#define LOG_E(x) do { printf("E:"); printf(x); } while (0)
#else
#define LOG_E(x) do ; while (0)
#endif
Then,
if (some_error)
LOG_E("Oops")
would result in a syntax error because of the missing semicolon, forcing you to write it as
if (some_error)
LOG_E("Oops");
Another thing you can do is concatenate the "E:" or "D:" tag with the passed in string, although this requires the parameter to be a string literal, rather than a general char *:
#define LOG_E(x) printf("E:" x)
Another thing you can do is to define the macro with a variable number of parameters (a variadic macro) to increase your options:
#define LOG_E(...) printf("E:" __VA_ARGS__)
Then you can do:
if (some_error)
LOG_E("Oops, got error: %d\n", some_error);
Another thing you can do is let the compiler optimize out the call to printf and define it like this:
#define LOG_E(...) do if (ENABLE_ERROR_LOG) printf("E:" __VA_ARGS__); while (0)
A decent compiler will notice that the if condition is constant and either optimize out the call to printf completely (if the constant condition is false), or include it (if the constant condition is true). For some compilers, you might need to suppress warnings about constant conditions in an if statement.
I am not sure if this is what you want, but you could check the #ifdef directive.
#include <stdio.h>
/* #define DEBUG */
#ifdef DEBUG
#define LOG_D(x) { printf("D: %s\n",x); }
#define LOG_E(x) { printf("E: %s\n",x); }
#else
#define LOG_D(x)
#define LOG_E(x)
#endif
int main() {
LOG_D("blah...");
return 0;
}
If you uncomment the #define DEBUG line, the program will print D: blah...
I've seen this topic which describes the "stringify" operation by doing:
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" STR(MAJOR_VER) STR(MINOR_VER)
Is it possible to stringify with leading zeros? Let's say my MAJOR_REV needs to be two characters "02" in this case and MINOR_REV 4 characters "0006"
If I do:
#define MAJOR_VER 02
#define MINOR_VER 0006
The values will be treated as octal elsewhere in the application, which I don't want.
No clean nor handy way to do it. Just as a challenge, here a possible "solution":
1) create a header file (e.g. "smartver.h") containing:
#undef SMARTVER_HELPER_
#undef RESVER
#if VER < 10
#define SMARTVER_HELPER_(x) 000 ## x
#elif VER < 100
#define SMARTVER_HELPER_(x) 00 ## x
#elif VER < 1000
#define SMARTVER_HELPER_(x) 0 ## x
#else
#define SMARTVER_HELPER_(x) x
#endif
#define RESVER(x) SMARTVER_HELPER_(x)
2) In your source code, wherever you need a version number with leading zeroes:
#undef VER
#define VER ...your version number...
#include "smartver.h"
at this point, the expression RESVER(VER) is expanded as a four-digit sequence of character, and the expression STR(RESVER(VER)) is the equivalent string (NOTE: I have used the STR macro you posted in you answer).
The previous code matches the case of minor version in your example,it's trivial to modify it to match the "major version" case. But in truth I would use a simple external tool to produce the required strings.
I believe in the example provided by the question sprintf is the correct answer.
That said, there are a few instances where you really want to do this and with C preprocessor if there is a will and somebody stupid enough to write the code there is typically a way.
I wrote the macro FORMAT_3_ZERO(a) which creates a three digit zero padded number using brute force. It is in the file preprocessor_format_zero.h found at https://gist.github.com/lod/cd4c710053e0aeb67281158bfe85aeef as it is too large and ugly to inline.
Example usage
#include "preprocessor_format_zero.h"
#define CONCAT_(a,b) a#b
#define CONCAT(a,b) CONCAT_(a,b)
#define CUSTOM_PACK(a) cp_ ## a __attribute__( \
(section(CONCAT(".cpack.", FORMAT_3_ZERO(a))), \
aligned(1), used))
const int CUSTOM_PACK(23);
Is it possible to stringify this C macro:
#define GPIO_INT_PIN (GPIO_PORT_D|GPIO_PIN_IRQ_RISING|GPIO_PIN5)
using something like
MY_STRINGFY(GPIO_INT_PIN)
to get
"(GPIO_PORT_D|GPIO_PIN_IRQ_RISING|GPIO_PIN5)" ?
Yes it is possible. Read about stringizing in GCC cpp documentation.
#define STRINGIFY(It) #It
#define MY_STRINGIFY(It) STRINGIFY(It)
I corrected my answer thanks to Wojtek Surowka's one
then use MY_STRINGIFY(GPIO_PORT_D|GPIO_PIN_IRQ_RISING|GPIO_PIN5) which would work much better if you use an enum to define the constants, e.g.
enum Gpio_stuff_en {
GPIO_PORT_D=5,
GPIO_PIN_IRQ_RISING=17,
GPIO_PIN5=23
};
Of course that won't work as you want if you need GPIO_PORT_D to be a macro, .e.g. because it expands to some non-constant-literal expression (like a variable, or an access to a field of some global structure, etc....)
As a counter-example:
#define FOO 1
#define BAR 2
#define STRINGIFY(s) #s
#define MY_STRINGIFY(s) STRINGIFY(s)
MY_STRINGIFY(FOO|BAR)
is expanded to "1|2" not to "FOO|BAR", if your remove the two #define-s for FOO and for BAR and replace them with
enum {
FOO=1,
BAR=2 };
you really get the expansion "FOO|BAR" as you want. Check with gcc -C -E ...
Also:
enum {FOO=1, BAR=2};
#define FOOORBAR (FOO|BAR)
#define STRINGIFY(s) #s
#define MY_STRINGIFY(s) STRINGIFY(s)
MY_STRINGIFY(FOOORBAR)
is expanded as "(FOO|BAR)" . But if you use #define for FOO and for BAR you get the "(1|2)" expansion.
Maybe you could add in your own header, after including the external header defining GPIO_PORT_D etc... as a literal constants, something like :
enum {en_GPIO_PORT_D= GPIO_PORT_D,
en_GPIO_PIN_IRQ_RISING= GPIO_PIN_IRQ_RISING,
en_GPIO_PIN5= GPIO_PIN5};
#undef GPIO_PORT_D
#undef GPIO_PIN_IRQ_RISING
#undef GPIO_PIN5
#define GPIO_PORT_D en_GPIO_PORT_D
#define GPIO_PIN_IRQ_RISING en_GPIO_PIN_IRQ_RISING
#define GPIO_PIN5 en_GPIO_PIN5
and then you'll get more readable stringified constants (but not exactly what you dream of).
If you have such two definitions
#define STRINGIFY(s) #s
#define MY_STRINGIFY(s) STRINGIFY(s)
MY_STRINGIFY does what you want - expands its argument and adds quotes after.