Page 1 of 1

code confusion???

Posted: Mon Dec 18, 2006 11:46 am
by rich_m
# define swap(a,b) temp=a; a=b; b=temp;

main( )
{
int i, j, temp;
i=5;
j=10;
temp=0;
if( i > j)
swap( i, j );
printf( "%d %d %d", i, j, temp);
}
[/code]

Posted: Mon Dec 18, 2006 12:52 pm
by rich_m

Posted: Tue Dec 19, 2006 1:59 am
by Solar
Erm... where is the problem?

Output is "5 10 0", becaue i > j is false and swap() never gets called...

Posted: Tue Dec 19, 2006 2:29 am
by AJ
I disagree :twisted:

Output is 10 0 0, because when the macro expands, the only line affected by the if statement will be temp=a.

a=b and b=temp will still execute.

Adam

Posted: Tue Dec 19, 2006 3:25 am
by Solar
:shock:

*slapshisforehead* *doesitagainjustHARDER*

You got me. I admit defeat. :lol:

Posted: Tue Dec 19, 2006 9:21 am
by Colonel Kernel
This is why macros are EVIL. :twisted:

Posted: Tue Dec 19, 2006 9:53 am
by Candy
Colonel Kernel wrote:This is why macros are EVIL. :twisted:
Macros not defined according to known flaws are evil.

The macro concept isn't a proper abstraction for not automatically hiding these kinds of things.

Macros created within the known fixes for flaws are not evil but useful. That's why they're still important to learn and widely used.

I'm hoping C++0x will be mainstream pretty soon since it includes a technique that allows more template metaprogramming that makes most macro metaprogramming superfluous, hopefully obsoleting it.

Posted: Tue Dec 19, 2006 7:05 pm
by Ready4Dis
Colonel Kernel wrote:This is why macros are EVIL. :twisted:
Bad programming is EVIL, that's why you should always use { and } after an if statement, then these problems don't happen. I love macro's, they make life easy :). You don't even want to see some of my source code for my virtual machine, lol, the entire thing is almost made of macro's. Very confusing to anybody trying to write software for it, but makes it very easy to add opcodes ;). For things to do with math, I just call

#define ADD +=
#define SUB -=
#define INC ++
#define DEC --

#define MATH(r1,r2,func)\
r1 func r2;\
SetFlags(r1);

#define OpCode(OpType,Func,Reg1,Reg2,Index)\
case Index:\
OpType(Reg1,Reg2,Func)\
break;


switch (Program[PC])
{
OpCode(MATH,ADD,REGINT1,REGINT2,0x01);
OpCode(MATH,SUB,REGINT1,REGINT2,0x02);
OpCode(MATH,INC,REGINT1,,0x03);
OpCode(MATH,DEC,REGINT1,,0x04);
};

This is pretty much how the entire things runs ;). Everything is inline, it's very simple to expand for me, and it is entirely macro driven.

Posted: Tue Dec 19, 2006 7:50 pm
by Colonel Kernel
Ready4Dis wrote:Bad programming is EVIL, that's why you should always use { and } after an if statement, then these problems don't happen.
I wouldn't call Solar's simple oversight a case of bad programming. It's a mistake that's all too easy to make. IMO we should design languages to make it harder to express mistakes, not easier. I would start by making the { and } mandatory for every control statement. :)

Posted: Tue Dec 19, 2006 10:15 pm
by m
Hi.
That's "interesting" :roll: ...
How about this:

Code: Select all

#define inc(x) x++
...
int a=2,b;
b=inc(a)*inc(a);    //What's the value of b?
...
and

Code: Select all

int inc(x){
    return x++;
}
...
int a=2,b;
b=inc(a)*inc(a);    //And now?
...
This case is easier to avoid than that one. :P
As you've said,it's caused by bad programming.When using a macro or other things for pre-processor it's may be necessary two check twice:
-if the macro has a side effect for its next call(esspecially when it's not explicit);
-if a single-line macro(#define) has a inner structure with a syntax indication or which is not complete one.
Whether the pre-processor is good depends on how you use it(I think). :)

Posted: Wed Dec 20, 2006 3:06 am
by Ready4Dis
Again, that example is bad programming. If my statement uses something like ++, or anything that can be passed to it with a math statement, I always put ( ) around it just incase. Also,

#define inc(x) (++x)

This is what you're looking for ;). The pre increment, rather than post increment. All else fails, cut/paste your macro into the code where it's broken, and it gives you a nicer view of what's going on! Macro's are very useful, but you do have to be careful and understand exactly how they are working. Also, the original problem could be fixed by doing this:

# define swap(a,b) {temp=a; a=b; b=temp;}

Then you need not worry if the for loop has { } or not. Just a little pre planning and you don't run into the problems.

btw, i didn't mean his programming in general was bad, just the way he did a few things, like not putting the { } in his for loop or putting containers around his macro just for cases like this.

Posted: Wed Dec 20, 2006 4:01 am
by Solar
Ready4Dis wrote:All else fails, cut/paste your macro into the code where it's broken, and it gives you a nicer view of what's going on!
You could also use gcc -E to get the output of the preprocessor. Some of the more "esoteric" constructs (#, ##...) might not be trivial to resolve by copy&paste.

Posted: Wed Dec 20, 2006 4:40 am
by m
Ready4Dis wrote: #define inc(x) (++x)
This is what you're looking for :wink: .
Aha! :P
Sorry for posting that in a hurry and thanks for pointing that out.