I have the defines with integer values in Cpp code. I need to call them in loop. How do I do that?
// Defines:
#define A0 0
#define A1 1
#define A2 2
// ...
#define A50 50
// Now based on loop I need to call these defines
for (int i = 0; i <= 50; i++){
function_name(A<i>, value);
}
#define macros are evaluated only by the preprocessor before the compiler is invoked. As such, preprocessor macros do not exist at runtime, and cannot be referred to by names that are built up using variables whose values are only known at runtime.
For what you are attempting, you will have to use an array, eg:
#define A0 0
#define A1 1
#define A2 2
...
#define A50 50
const int A[51] = {A0, A1, A2, ..., A50};
...
for (int i = 0; i <= 50; i++){
function_name(A[i], value);
}
Related
I'm trying to define a preprocessor macro that in turn selects the right macro depending on the value of an argument.
#define BIT_8(n) n, "is lower or equal than 8"
#define BIT_N(n) n, "is greater than 8"
#define BIT(n) ?????
int main() {
printf("%d %s", BIT(9));
return 0;
}
BIT(n) should expand to:
BIT_8(n) if n≤8
BIT_N(n) if n>8
Any way to achieve this?
Unless you want very clumsy code, you can't do that. The preprocessor has no idea about the value of the argument passed in. It's just doing string replacement and that's all.
That being said, they are crazy guys implementing BIT_x for all x in [0 to 63].
This is very ugly and would fail is used with an argument set at 64.
A clean solution is to use a function instead:
const char * bit_msg(unsigned int b)
{
if (b > 8) return "is greater than 8";
const char * bits[] = {
"is 0 and lower than 8",
"is 1 and lower than 8",
"is 2 and lower than 8",
"is 3 and lower than 8",
"is 4 and lower than 8",
"is 5 and lower than 8",
"is 6 and lower than 8",
"is 7 and lower than 8",
"is 8",
};
return bits[b];
}
#define BIT(X) X, bit_msg(X)
[...]
printf("%d %s", BIT(9));
Because you've tagged the question with C++ and to follow #Romen you could achieve similar result using constexpr that, if possible, will be computed by the compiler at compile time, resulting in code that's as efficient as a macro.
In the example above, you'll just need to replace the signature with constexpr const char * bit_msg(unsigned int b) and the compiler might even skip the function and write (the equivalent of) printf("%d %s", 9, "is greater than 8").
The challenge is that the pre-processor doesn't know math. You can solve this problem by implementing the math you need, but it gets UGLY. For example, here's working pre-processor code for what you want to do:
#include <stdio.h>
#define BIT_8(n) n, "is lower or equal than 8"
#define BIT_N(n) n, "is greater than 8"
// Identify values less than 8; make the second argument 8
#define LT_8_0 ~,8
#define LT_8_1 ~,8
#define LT_8_2 ~,8
#define LT_8_3 ~,8
#define LT_8_4 ~,8
#define LT_8_5 ~,8
#define LT_8_6 ~,8
#define LT_8_7 ~,8
#define LT_8_8 ~,8
// Helper macros. Delays let arguments be processed before the macros is run.
#define MERGE(A, B) A ## B
#define MERGE_DELAY(A, B) MERGE(A,B)
#define ARG2(A,B,...) B
#define ARG2_DELAY(A,B,...) ARG2(A,B,__VA_ARGS__)
// Return 8 or N depending if n <= 8...
#define LT_8(n) ARG2_DELAY( MERGE(LT_8_, n), N,~ )
#define BIT(n) MERGE_DELAY(BIT_, LT_8(n))(n)
int main() {
printf("%d %s\n", BIT(9));
return 0;
}
Note that the LT_8 macro works by taking the second of a series of arguments. We default that second argument to N, but if we recognize the input number to be 8 or less, we insert a new second argument of 8.
you could do this
#include <stdio.h>
#define BIT_8(n) printf("%d is lower than or equal to 8 \n" , n)
#define BIT_N(n) printf("%d is greater than 8 \n" , n)
#define BIT(n) ((n <= 8) ? (BIT_8(n)) : (BIT_N(n)))
int main() {
BIT(7);
BIT(8);
BIT(9);
return 0;
}
Not sure how to word this but, Is there any way to increment a macro?
I have several offset macros, the first defined offset must be zero, the next one must be 1, and so on.
If I need to add an offset macro to the middle of the list, it can be cumbersome to increment all the offsets below it manually.
//How can I turn this...
// v This number needs to increment by 1 (no matter the order)
#define OFFSET_X 0
#define OFFSET_Y 1
#define OFFSET_Z 2
#define OFFSET_W 3
//Into something like this... (order of macros swapped yet the numbering still goes from 0 to 3)
int num = 0;
#define OFFSET_Z num++ // = 0 (was 2)
#define OFFSET_Y num++ // = 1 (was 1)
#define OFFSET_X num++ // = 2 (was 0)
#define OFFSET_W num++ // = 3 (was 3)
With the original order,
#define OFFSET_X 0
#define OFFSET_Y (OFFSET_X + 1)
#define OFFSET_Z (OFFSET_Y + 1)
#define OFFSET_W (OFFSET_Z + 1)
or with the revised order in the second part of your post,
#define OFFSET_Z 0
#define OFFSET_Y (OFFSET_Z + 1)
#define OFFSET_X (OFFSET_Y + 1)
#define OFFSET_W (OFFSET_X + 1)
etc. Since all this gets evaluated at compile time, anyway, there's no perf hit.
Or you could write a code generator, if you're really bored, and have it generate the values for you.
Or just use an enum. This is what they're for, and they're treated as constants by the compiler, anyway - but you get compile-time error checking which is far less effective with macros.
BUT, a better solution may be constexpr added in C++11.
In any case, if you only have four of these, this is overkill.
Just use an enum:
enum class offsets {
X = 0,
Y = 1,
Z = 2,
W = 3
};
and don't sweat it. Want auto-increments? Even easier:
enum class offsets { X = 0, y, z, w };
for the same effect.
Note I've suggested an enum class, so the usage is offsets::X, offsets::Y etc.
In some cases you may prefer an constexpr std::array, which you could then iterate over (something you can't do with macros or enums).
#include <iostream>
using namespace std;
#ifndef R
#define N1 10
#ifndef R
#define N2 11
#endif
#endif
int main(){
cout << N2 << endl;
}
From my understanding if R is not defined then N1 will be 10.
And second case where again R is defined again it should not be able to define N2 as 11, because R is already defined. I am just confused about it, And one Can please help to understand the point I have missed.
Let's walk through the code:
#ifndef R
R hasn't been defined yet, so step into the branch:
#define N1 10
N1 becomes 10
#ifndef R
R still hasn't been defined yet, so step into nested branch
#define N2 11
N2 is assigned to 11
#endif
Ends the nested branch
#endif
Ends the primary branch
So in the end R was never defined, so we assign N2 successfully.
You need to explicitly #define R or use -DR in the compiler line to define R, it won't get defined for you within a ifndef R branch.
The second #ifndef is redundant the way you currently have it organized. I'll write this out in a clearer pseudo code
IF R IS NOT DEFINED
SET N1 = 10
IF R IS NOT DEFINED
SET N2 = 11
END IF
END IF
This can be more simply
IF R IS NOT DEFINED
SET N1 = 10
SET N2 = 11
END IF
or in C/C++ preprocessor notation
#ifndef R
#define N1 10
#define N2 11
#endif
#define N 1
#define A(N) #N
#define S_A A(N)
#define B_(N) #N
#define B(N) B_(N)
#define S_B B(N)
#include <stdio.h>
int main(void) {
puts(S_A);
puts(S_B);
}
outputs N and 1 instead of two 1s.
Why is the extra indirection making a difference?
It works different because the macro expansion of N only happens on the "use" of N. So S_A exands to A(N), which is expanded to #N. In S_B it is expanded to B(N), which is expanded to _B(1), and then #1. Why? Well, how would you do something like:
#define COMBINE(A, B) A##B
#define foo 1
#define bar 2
int COMBINE(foo, bar) = 34;
so that it generates int foobar = 34;, and not the illegal int 12 = 34;.
Did you intend to use a ## operator for token pasting?
puts(S_A); //Gets expanded into puts(A(N)) --> puts(#N)
and
puts(S_B); //Gets expanded into puts(B(N)) --> puts(_B(1)) --> puts(#1)
Without affecting your macros much, if you intend to print 1,1 both the times, you could Use the macros this way:
#define N "1" //instead of 1
#define A(N) N //instead of #N
#define B_(N) N //instead of #N
Why won't this work?
0. #define CONCAT(x, y) x ## y
1.
2. #define VAR_LINE(x) \
3. int CONCAT(_anonymous, __LINE__) = x
4.
5. #define VAR_LINE2(x) \
6. int _anonymous ## x = 1
7.
8. int main()
9. {
10. VAR_LINE(1);
11. VAR_LINE(1);
12. VAR_LINE(1);
13. VAR_LINE2(__LINE__);
14. }
The result from the above macro expansion
int _anonymous__LINE__ = 1;
int _anonymous__LINE__ = 1;
int _anonymous__LINE__ = 1;
int _anonymous13 = 1;
It would be convenient if I didn't have to write that __LINE__ macro as an argument.
I'm thinking the problem is pretty clear. I want to be able to generate anonymous variables so that this macro doesn't fail with redefinition error when declaring several variables within the same scope. My idea was to use the predefined __LINE__ macro because no variable will ever be declared on the same line like this. But the macro expansion troubles me, can you help?
Update: Correct answer
Thanks to Luc Touraille. However, there was a tiny problem with the suggested solution. There has to be whitespace between the operands and the ## operator (apparently the standard says otherwise but the the PS3 flavoured GCC would not expand the macro properly if there were no whitespace between the operator and operands).
#define _CONCAT(x,y) x ## y
#define CONCAT(x,y) _CONCAT(x,y)
The VAR_LINE macro now yields:
int _anonymous10 = 1;
int _anonymous11 = 1;
int _anonymous12 = 1;
This has been verified to work under Win32 (Visual Studio 2008), XBOX360 (Xenon) and PS3.
You need to add a level of indirection so that __LINE__ will be expanded:
#define _CONCAT_(x,y) x ## y
#define CONCAT(x,y) _CONCAT_(x,y)
#define VAR_LINE(x) int CONCAT(_anonymous, __LINE__) = x