strange output

D

dis_is_eagle

Hi.I could not understand the output of the following program.

#define swap(a,b) temp=a; a=b; b=temp;
int main( )
{
int i, j, temp;
i=5;
j=10;
temp=0;
if( i > j)
swap( i, j );
printf( "%d %d %d", i, j, temp);
return 0;
}
The output is 10 0 0. Thanks for any help.
Regards,
Eric
 
M

manoj1978

Hi.I could not understand the output of the following program.

#define swap(a,b) temp=a; a=b; b=temp;
if( i > j)
swap( i, j );

After expanding this will become
if( i > j)
temp=i; i=j; j=temp;;
since i is not greater than j,
temp=i wont be executed.

Read FAQ 10.4 for writing function like macro.
 
R

ramasubramanian.rahul

hi...
put brackets like shown below
#define swap(i,j) ( the code you have written...)
this ensures all code of swap is either executed or left out..
in the current code .. last two statements of # define always work
irrespective of the if condition...
therefore you are getting some wierd behaviour in your program....
thanks and regards...
rahul
 
A

Ancient_Hacker

The problem is when the macro gets expanded, you end up with the if()
statement controlling just the first statement of the macro.

hat's an intrinsic drawback to languages where the statements accept
just one statement or a block. Even worse are languages like COBOL
where COMMENTS count as statements. Now that's really brain-dead. Go
back to a working program to add a few comments and you can easily
break things! But I digress.


You should make that a block of statements by putting {}'s around the
whole macro:

#define swap(a,b) { ..... }

Also keep in mind the drawbacks to using macros-- excessive use of them
leads to confusing looking code that can be barely impossible to
understand or debug.


T
 
C

CBFalconer

Hi.I could not understand the output of the following program.

#define swap(a,b) temp=a; a=b; b=temp;
int main( )
{
int i, j, temp;
i=5;
j=10;
temp=0;
if( i > j)
swap( i, j );
printf( "%d %d %d", i, j, temp);
return 0;
}
The output is 10 0 0. Thanks for any help.

Please indent your code properly. Don't use tabs.

After expansion the lines

if (i > j)
swap(i, j);

become

if (i > j)
temp = a; a = b; b = temp;

which, when properly indented, is:

if (i > j)
temp = a;
a = b; b = temp;

which is not what you want. Redefine the macro as:

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

and all will be well.
 
F

Frederick Gotham

Ancient_Hacker posted:
You should make that a block of statements by putting {}'s around the
whole macro:

#define swap(a,b) { ..... }

Either:

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

Or:

#define swap(a,b) (temp=(a),(a)=(b),(void)(b)=temp)
 
C

CBFalconer

Frederick said:
Ancient_Hacker posted:


Either:

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

Or:

#define swap(a,b) (temp=(a),(a)=(b),(void)(b)=temp)

No. Only the do while (0) method will work in all circumstances.
With the braces you will get errors with:

if (condition) swap(x, y);

because of the terminal semicolon.
 
B

Bart Rider

CBFalconer said:
Please indent your code properly. Don't use tabs.

After expansion the lines

if (i > j)
swap(i, j);

become

if (i > j)
temp = a; a = b; b = temp;

which, when properly indented, is:

if (i > j)
temp = a;
a = b; b = temp;

which is not what you want. Redefine the macro as:

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

and all will be well.

Your macro (the same as Fredericks) left me curious.
Why is there a need for do{ ... }while(0)? Isn't it
sufficient to simply use curly brackets? like

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

With this the if statement in the OPs example is
properly expanded. Maybe you have an example, where
only braces are not sufficient...

Best regards,
Bart
 
S

Spiros Bousbouras

Bart said:
Your macro (the same as Fredericks) left me curious.
Why is there a need for do{ ... }while(0)? Isn't it
sufficient to simply use curly brackets? like

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

With this the if statement in the OPs example is
properly expanded. Maybe you have an example, where
only braces are not sufficient...

Whether braces are sufficient or not depends on how you're
going to use the macro in your code. If you use it as
some_macro(arguments)
**without** a semicolon in the end , then braces will always
be sufficient. That's the style I prefer. But some would consider
it unnatural since statements in C are terminated by semicolons.
So you might be tempted to write instead
some_macro(arguments) ;
This will work in many cases. But consider the following code snipet
if (something)
some_macro(arguments) ;
else {
some code
}

This will expanded to
if (something)
{macro statements} ;
else {
some code
}

In this case the if block gets terminated in the semicolon
which follows the macro expansion so the else will produce
an error or even worse might be considered as the else clause
of a different if than the one you intended.

On the other hand if the macro had been defined with the
do...while(0) trick then the code would be expanded to
if (something)
do {macro statements} while(0) ;
else {
some code
}

which works as intended.
 
F

Frederick Gotham

Spiros Bousbouras posted:
On the other hand if the macro had been defined with the
do...while(0) trick then the code would be expanded to
if (something)
do {macro statements} while(0) ;
else {
some code
}

which works as intended.


And don't forget to put parentheses around:

(1) Each macro argument
(2) The entire macro

E.g.:

#define SUBTRACT(a,b) ((a)-(b))

, reason being that it could be "invoked" as follows:

SUBTRACT(54+3,76+Func());

You should also warn wherever a macro will evaluate any of its arguments
more than once:

/* BEWARE: This performs multi-evaluation */

#define SQUARE(x) ((x)*(x))
 
A

Ancient_Hacker

Thanks for the {} embellishments to allow a trailing semicolon.
The point of putting parens around the macro parameters is usually a
good suggestion, except in the case in point, swap(a,b), kinda implies
both parameters resolve to addresses, or lvalues. So parens tend to be
superflous in this special case.
 
P

pete

CBFalconer said:
No. Only the do while (0) method will work in all circumstances.
With the braces you will get errors with:

if (condition) swap(x, y);

because of the terminal semicolon.

I disagree.
There's nothing wrong with:

if (condition) (temp=(a),(a)=(b),(void)(b)=temp);
 
C

CBFalconer

Bart said:
Your macro (the same as Fredericks) left me curious.
Why is there a need for do{ ... }while(0)? Isn't it
sufficient to simply use curly brackets? like

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

With this the if statement in the OPs example is
properly expanded. Maybe you have an example, where
only braces are not sufficient...

No. Consider what happens when you use the macro in an if-else
statement:

if (something) swap(x, y);
else dosomethingelse();

The swap needs to have a terminal ; if it is a normal function
call. If you use the semi with the brace enclosed macro, you will
get a syntax error. The do-while is proof against this.
 
P

pete

Hi.I could not understand the output of the following program.

#define swap(a,b) temp=a; a=b; b=temp;
int main( )
{
int i, j, temp;
i=5;
j=10;
temp=0;
if( i > j)
swap( i, j );
printf( "%d %d %d", i, j, temp);
return 0;
}
The output is 10 0 0.

/* BEGIN new.c */

#include <stdio.h>

#define swap(a, b, temp) \
((void)(*(temp) = *(a), *(a) = *(b), *(b) = *(temp)))

int main(void)
{
int i, j, temp;

i = 5;
j = 10;
temp = 0;
if (j > i) {
swap(&i, &j, &temp);
}
printf( "%d %d %d\n", i, j, temp);
return 0;
}
/*
** The output is 10 5 5.
*/
/* END new.c */
 
R

Richard Tobin

[/QUOTE]

You get a problem with the braces, but not with the parenthesised
version.
True.

You never follow an "if" with an "else"?

The parenthesised version, with a semicolon, is fine in that case.

The do { } version has the advantage that you can include declarations.

-- Richard
 
C

Clark S. Cox III

CBFalconer said:
You never follow an "if" with an "else"?

There's still nothing wrong with it (after fixing the "(void)" cast)

//BEGIN CODE
#include <stdio.h>

int main()
{
int temp, a = 15, b = 255;

if(1) (temp=(a),(a)=(b),(void)((b)=temp));
else (a = 0,b = 0);

printf("a = %d\nb = %d\n", a, b);

return 0;
}
//END CODE
 
K

Keith Thompson

Ancient_Hacker said:
Thanks for the {} embellishments to allow a trailing semicolon.
The point of putting parens around the macro parameters is usually a
good suggestion, except in the case in point, swap(a,b), kinda implies
both parameters resolve to addresses, or lvalues. So parens tend to be
superflous in this special case.

Please include context.

There's no reason not to paranthesize the parameters. An lvalue is a
kind of expression; a parenthesized lvalue is still an lvalue.
 
C

Charles Richmond

CBFalconer said:
Please indent your code properly. Don't use tabs.

After expansion the lines

if (i > j)
swap(i, j);

become

if (i > j)
temp = a; a = b; b = temp;

which, when properly indented, is:

if (i > j)
temp = a;
a = b; b = temp;

which is not what you want. Redefine the macro as:

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

and all will be well.

What about:

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

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top