Reputation: 33
Here I know that the following code simply copies the character i
rather than its value to the preprocessor statement (which makes a error for undefined symbol i
in compile-time).
What I want is:
Is their a way such that the compiler treats, i
as a variable with some value rather than a character ?
#include <stdio.h>
#define PRINT(x) printf("%d \n", y ## x)
int main(void) {
int y1=0 , y2=1 , y3=4;
for(int i=1; i <= 3; ++i) {
PRINT(i);
}
return 1;
}
Upvotes: 2
Views: 155
Reputation: 14104
First of all, I think there's a need to clarify how the preprocessor works: it pre-processes the input files, which means it runs before the compiler. Unfortunatly, for historical reasons, it doesn't know anything about C or C++, doesn't parse anything, and just does very simple textual operations on words and parenthesis. Just to illustrate my point:
#define this __FILE__
#define file -- Hell no!
#define fine(a, b) fine: a ## _ ## b
Ok, so this is not a valid C or C++ file
But the preprocessor will run just fine(go, try!)
Run this with a pre-processor, for example gcc -x c -E -P test.txt
and you'll get:
Ok, so "test.txt" is not a valid C or C++ -- Hell no!
But the preprocessor will run just fine: go_try!
So, obviously, when the preprocessor sees PRINT(i)
in your code, it replaces it with printf("%d \n", yi)
without thinking much about it. And it has absolutely no idea i
is a variable, don't even think about evaluating it's value.
Basically, what you want is print a bunch of numbers.
You could simply do
printf("0\n1\n4\n");
But this lacks makes changing numbers cumbersome,
so let's go with
printf("%d\n%d\n%d\n", 0, 1, 4);
Which makes it easy to change a number, but not to add/remove one.
Ok so how about:
printf("%d\n", 0);
printf("%d\n", 1);
printf("%d\n", 4);
Yeah, you can change/add/remove numbers easily but as any sane programmer you hate repetition. So, we need some kind of loop.
By far the simplest and most straightforward way to iterate in C is at runtime, using an array:
int [] y = { 0, 1, 4 };
for(int i = 0; i < sizeof(y)/sizeof(int); ++i) {
printf("%d\n", y[i]);
}
If you want, you can hide the printf
using a function:
inline void print_int(int* y, int i) { print_int(y[i]); }
int [] y = { 0, 1, 4 };
for(int i = 0; i < sizeof(y)/4; ++i) print_int(y, i);
And going further with functions:
inline void print_int(int x) { printf("%d\n", x); }
inline void print_int(int* y, int i) { print_int(y[i]); }
inline void print_ints(int * y, int n)
{
for(int i = 0; i < n; ++i)
print_int(y, i);
}
template<int n> // C++
inline void print_ints(const int[n] & y) { print_ints(&y[0], n); }
int [] y = { 0, 1, 4 };
print_ints(y); // C++
// or in C:
print_ints(y, sizeof(y)/sizeof(int));
Now, what if you absolutely want the generated code to look like solution 3. ? This means you need the iteration to happen at compile-time. Tricky!
That's where the preprocessor can come into play. There are (hacky) ways to make it do this kind of things. I strongly recommend not implementing this yourself (except to play), but use the Boost.preprocessor
library instead:
#define PRINTER(R,D, NUMBER) printf("%d\n", NUMBER);
#define NUMBERS (0, 1, 4)
BOOST_PP_LIST_FOR_EACH(PRINTER, _, BOOST_PP_TUPLE_TO_LIST(NUMBERS))
// will expand to printf("%d\n", 0); printf("%d\n", 1); printf("%d\n", 4);
Upvotes: 4
Reputation: 11716
Under standard C, this is not possible; during preprocessing, the compiler simply sees the identifier i
as simply that - an identifier. It does not know that i
is of type int
, or that it's even a variable in the first place.
The easiest way to achieve what's intended is to use an array, like so:
int i;
int y[] = { 0, 1, 4 };
for (i = 0; i < 3; i++) // NOTE: arrays in C start at index 0, not 1
{
printf("%d \n", y[i]);
}
Also note that I got rid of the macro, as you want to use the value of a runtime variable i
to select another runtime variable.
Upvotes: 0