Consider the following code i managed to write:
#include <stdio.h>
#define FOR(A, B, C) for(A; B; C++)
int main()
{
FOR(i=0, i<10, i)
printf("%i", i);
return 1;
}
The output is:
0123456789
If i do FOR(i=5, i<10, i)
then respectively the output is 56789
My questions are is that legal? Will it cause any errors in different cases? Does it works exactly like a for loop?
Yes it's a "legal" macro, but no, it does not work like a real for loop.
Your macro won't handle this:
int a, b;
for(a = 0, b = 4711; a < b; ++a);
for instance, since you can't distinguish the , used to build a longer initializing expression to the one used to separate the expressions that make up the parts:
FOR(a = 0, b = 0, a < b, ++a);
will break, since it looks like a call with 4 arguments instead of 3.
A macro is just copied everywhere the preprocessor sees you using the macro keyword. It just copies the text, nothing more.
To elaborate on that a bit more, consider this example:
#define MY_MACRO a
int MY_MACRO = 5;
When the preprocessor comes along it will take the above and change it to:
int a = 5;
and then the compiler will come along and compile it like normal C/C++ code.
When you add arguments to your macro, they are just substituted in place within your macro. This can be a problem, consider the following two macros:
#define BAD_MACRO(a, b) a*b
#define GOOD_MACRO(a, b) (a)*(b)
They look almost the same, but consider the following:
int k = BAD_MACRO(2, 3); // k = 2*3 = 6
int j = GOOD_MACRO(2, 3); // j = 2*3 = 6
int m = BAD_MACRO(2+1, 3); // m = 2+1*3 = 5
int n = GOOD_MACRO(2+1, 3); // n = (2+1)*3 = 9
Although note that neither of these macros are good or bad, they just don't have the same behaviour as a typical function.
Related
If you call something like this in C:
#include <stdio.h>
#define REPS ,a
...
int a = 1;
printf("%d" REPS);
It will work, but is it possible to call the REPS macro multiple times based on an unknown value, like for example, that I want to have five inputs in a scanf, yet I want my code to automate it (for example, if #define REPS ,a[i] then: ... ,a[1] ,a[2])?
It will work, but is it possible to call the REPS multiple times based in an unknown value
No. #define creates a preprocessor macro that you can use in your code, but when the compiler compiles your code, the actual value is substituted for the macro. If you have:
#define FOO 7
for example, then every occurrence of FOO in your code is replaced by 7 before the code is compiled; by the time the compiler sees your code, there's no #define and no FOO, only 7 wherever FOO was. Although there are some other preprocessor commands (e.g. #if) that can control whether a given #define is evaluated at all, there are no other preprocessor control structures (loops etc.).
I want to have five inputs in a scanf, yet I want my code to automate it (for example, if #define REPS ,a[i] then: ... ,a[1] ,a[2])?
You can certainly automate something like that; it's just that the preprocessor isn't the right tool for the job. Consider:
int reps = 5
//...
for (int i = 0; i < reps; i++) {
scanf(" %d", &a[i]);
}
REPS is evaluated at compile time, so it cannot depend on run-time values in this case a. There are hacks but in general you cannot do compile loops with macros.
I suggest you write a function along these lines instead:
#include <stdio.h>
void print_int_array(size_t n, int a[n]) {
for(int i = 0; i < n; i++)
printf("%d%s", a[i], i + 1 < n ? ", " : "\n");
}
int main() {
print_int_array(0, (int []) {});
print_int_array(1, (int []) {1});
print_int_array(2, (int []) {1, 2});
}
I programmed a simple clock and found that while hours and seconds are okay, minutes are not if I declare the variables on a single line (minutes starts at 16 and not at 0 as expected).
The problem is solved if I declare the variables on separated lines. I'm still curious though, anybody knows why?
Here's the code:
#include <stdio.h>
#include <windows.h>
//h=hours, m=minutes, s=seconds.
int main(){
int h, m, s = 0; //THIS IS THE LINE: WHY "m" STARTS AT 16 AND NOT 0?
int delay = 1000;
while(1){
s++;
if(s>59){
m++;
s=0;
}
if(m>59){
h++;
m=0;
}
if(h>12){
h=1;
}
printf("\n %02d:%02d:%02d", h, m, s);
Sleep(delay);
system("cls");
}
}
Your variables are uninitialized - they can take any value, and using them before initialization is (usually) indeterminate behavior.
A line of code like:
int h, m, s = 0;
does not define each variable to be zero - only the third one. It is equivalent to:
int h;
int m;
int s = 0;
To fix, initialize all of your variables as zero:
int h = 0, m = 0, s = 0;
You haven’t initialized h or m, so their initial values might whatever was in that memory already, or something else entirely. C does not automatically initialize variables to 0.
When you declare multiple variables on one line, the value only applies to the variable it comes after. So
int a, b, c = 5;
only sets c to 5, while
int a = 1, b = 2, c = 3;
initializes all of them. In your case, you just need to use
int h = 0, m = 0, s = 0;
You compiler likely has an option for warnings (-Wall in gcc), which should warn you about using an uninitialized variable.
int h, m, s = 0; // THIS IS THE LINE: WHY "m" STARTS AT 16 AND NOT 0?
Well, I guess, because C is not English. The "= 0" part applies just to that one variable name s, not to the whole line.
Although, you know, English doesn't necessarily apply modifiers to the whole line, either. If I say "There were three people standing on the streetcorner: A man, a woman, and a boy named Brad", you would not infer that the man and the woman were named Brad, too, would you?
[Footnote: Now I've got that old song "Me and you and a dog named Boo" stuck in my head. :-) ]
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;
}
About the pre-processor
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.
Solutions
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);
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.
Why is the answer for the below code 16? Can anybody explain the working of this program?
#define SQUARE(n) n*n
void main()
{
int j;
j =16/SQUARE(2);
printf("\n j=%d",j);
getch();
}
If we write the same code like below, then the answer is 4:
//the ans is 4 why?
#include<stdio.h>
#include<conio.h>
#define SQUARE(n) n*n
void main()
{
int j;
j =16/(SQUARE(2));
printf("\n j=%d",j);
getch();
}
The preprocessor just replaces the text, exactly as written.
So, the macro call SQUARE(2) becomes literally 2*2.
In your case, that means the whole expression becomes 16/2*2, which because of C's precedence rules evaluates to (16/2)*2, i.e. 16.
Macros should always be enclosed in parenthesis, and have each argument enclosed as well.
If we do that, we get:
#define SQUARE(n) ((n) * (n))
which replaces to 16/((2) * (2)), which evaluates as 16/4, i.e. 4.
The parens around each argument makes things like SQUARE(1+1) work as expected, without them a call such as 16/SQUARE(1+1) would become 16/(1+1*1+1) which is 16/3, i.e. not at all what you'd want.
Order of operations. Your expression is evaluating to:
j = 16 / 2 * 2
which equals 16. Make it:
#define SQUARE(n) (n*n)
which will force the square to be evaluated first.
You need to define your macro with insulating parentheses, like so:
#define SQUARE(n) ((n)*(n))
Otherwise
j = 16/SQUARE(2);
expands to
j = 16 / 2 * 2; which is equivalent to (16 / 2) * 2
When what you want is
j = 16 / (2 * 2);
1. When using macros that are to be used as expressions, you should parenthesise the whole macro body.
This prevents erroneous expansions like:
#define SQUARE(x) x*x
-SQUARE(5,5)
// becomes -5 * 5
2. If the macro arguments are expreessions, you should parenthesise them too.
This prevents a different type of problems:
#define SQUARE(x) x*x
SQUARE(5+2)
// becomes 5 + 2*5 + 2
Hence the correct way is to write it like this:
#define square(n) ((n)*(n))
-SQUARE(5+2)
// becomes -((5+2)*(5+2))
Using macros as functions is discouraged though (guess why), so use a function instead. For instance:
inline double square(n) { return n*n; }
The Expansion of macro will be like:
j = 16/SQUARE(2);
j = 16/2*2;
Which is equal to : j = (16/2)*2; Means j = 16;
and :
j = 16/(SQUARE(2));
j = 16/(2*2);
Which is equal to : j = 16/4; Means j = 4;
Because the macro will be expanded as:
j = 16/2*2;
The pre-compiler does not do any processing on the expansion. It places the expanded macro in your code as it is. Since you have not parenthesized the replacement text it wont do it for you in the main code as well. Make it :
#define SQUARE(n) ((n)*(n))
The first example is evaluated as:
16 / 2 * 2
(16 / 2) * 2
8 * 2
16
The second example is evaluated as:
16 / (2 * 2)
16 / 4
4
Add parenthesis to you preprocessor statement to control the order of operations:
#define SQUARE(n) ((n)*(n))
The outer parenthesis in ((n)*(n)) ensure that n is squared before any outside operation is performed. The inner parenthesis (n) ensure that n is correctly evaluated in cases where you pass an expression to SQUARE like so:
16 / SQUARE(2 * 2)
16 / ((2 * 2)*(2 * 2))
16 / (4 * 4)
16 / 16
1
you'll get
j =16/2*2; // (16 / 2) * 2 = 16
Its because Whenever macro name is used, it is replaced by the contents of the macro.its simple rule of working of macro.
Case 1 : result 16
define SQUARE(n) n*n
void main()
{
int j;
j =16/SQUARE(2);
printf("\n j=%d",j);
getch();
}
its get expand as below
j =16/SQUARE(2);
so in place of SQUARE(2) it will replace 2*2 because Macro is SQUARE(n) n*n
j = 16/2*2
j = (16/2)*2
j = 8*2
j =16
Case 2 : result 4
define SQUARE(n) n*n
void main()
{
int j;
j =16/(SQUARE(2));
printf("\n j=%d",j);
getch();
}
its get expand as below
j =16/(SQUARE(2));
so in place of SQUARE(2) it will replace 2*2 because Macro is SQUARE(n) n*n
j = 16/(2*2)
j = 16/(4)
j = 4
Hope this will help
Consider:
enum Test
{
a = 3,
b = 7,
c = 1
};
I want to access the enum using an index. Something like this:
for (i=0; i<n; i++)
doSomething((Test)i);
How can I do something like this, where I will be able to access the enum using an index, though the members of the enum have different values?
This is the best you can do:
enum Test { a = 3, b = 7, c = 1, LAST = -1 };
static const enum Test Test_map[] = { a, b, c, LAST };
for (int i = 0; Test_map[i] != LAST; i++)
doSomething(Test_map[i]);
You have to maintain the mapping yourself.
You can't do that. A C enum is not much more than a bunch of constants. There's no type-safety or reflection that you might get in a C# or Java enum.
Your question demonstrates you don't really understand what an enum is for.
It is not something that can be indexed, nor is there ever any reason to. What you have defined is actually just 3 constants named a, b, and c, whose values are 3, 7, and 1 respectively.
As someone else mentioned, this is not the purpose of an enum. In order to do what you are asking, you can simply use an array:
#define a 3
#define b 7
#define c 1
int array[3] = { a, b, c };
int i;
for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) {
doSomething( array[i] );
}