K&R exercise 4-14

K

Kevin Zhou

The question is "define a macro swap(t,x,y) that interchanges two
arguments of type t".
What does it mean? what are arugments of a type? I can't find an
explanation in the book.
 
B

Ben Pfaff

Kevin Zhou said:
The question is "define a macro swap(t,x,y) that interchanges two
arguments of type t".
What does it mean? what are arugments of a type? I can't find an
explanation in the book.

Types don't have arguments. The macro takes three arguments.
The first (t) is a type, and the second and third (x and y) have
the type specified by the first argument.
 
B

Ben Pfaff

Kevin Zhou said:
#define swap(t,x,y) do{t z=x;x=y;y=z}while(0)

why a do while "loop" is necessay ?

This is in the C FAQ.

10.4: What's the best way to write a multi-statement macro?

A: The usual goal is to write a macro that can be invoked as if it
were a statement consisting of a single function call. This
means that the "caller" will be supplying the final semicolon,
so the macro body should not. The macro body cannot therefore
be a simple brace-enclosed compound statement, because syntax
errors would result if it were invoked (apparently as a single
statement, but with a resultant extra semicolon) as the if
branch of an if/else statement with an explicit else clause.

The traditional solution, therefore, is to use

#define MACRO(arg1, arg2) do { \
/* declarations */ \
stmt1; \
stmt2; \
/* ... */ \
} while(0) /* (no trailing ; ) */

When the caller appends a semicolon, this expansion becomes a
single statement regardless of context. (An optimizing compiler
will remove any "dead" tests or branches on the constant
condition 0, although lint may complain.)

If all of the statements in the intended macro are simple
expressions, with no declarations or loops, another technique is
to write a single, parenthesized expression using one or more
comma operators. (For an example, see the first DEBUG() macro
in question 10.26.) This technique also allows a value to be
"returned."

References: H&S Sec. 3.3.2 p. 45; CT&P Sec. 6.3 pp. 82-3.
 
C

CBFalconer

M

Malcolm

Kevin Zhou said:
#define swap(t,x,y) do{t z=x;x=y;y=z}while(0)

why a do while "loop" is necessay ?
This is a really bad exercise. Macros in C are word-processing commands,
which means that you have to do lots of tricks to do anything beyond the
simple
#define constant 123
or an extremely simple function. Even min and max have problems if arguments
have side effects, and need lots of ugly parentheses to cope with compound
arguments.

If we didn't use the do ... while trick we would have a floating {} block,
which is illegal.
 
E

Emmanuel Delahaye

In 'comp.lang.c' said:
The question is "define a macro swap(t,x,y) that interchanges two
arguments of type t".
What does it mean? what are arugments of a type? I can't find an
explanation in the book.

Bad parsing:

"define a macro swap(t,x,y) that interchanges two arguments <breath> of type
t"
 
E

Emmanuel Delahaye

If we didn't use the do ... while trick we would have a floating {}
block, which is illegal.

Wow! Since when has a 'floating block' been illegal? I'm curious. I use it
daily to stick to my 'reduce the range of the objects' policy...

No, the reason for the do-while trick in macros is to force the use of the
final ';' in the source code. Isn't it explained like that in the FAQ?
 
K

Kevin Zhou

Nick said:
I hope that before you submit your coursework you can
find and fix the deliberate typo. :)

Nick.
Actually I'm learning C from the book for fun.
 
G

Gregory Pietsch

Kevin Zhou said:
The question is "define a macro swap(t,x,y) that interchanges two
arguments of type t".
What does it mean? what are arugments of a type? I can't find an
explanation in the book.

It means that the two arguments x and y have an undetermined type t.

I wrote some of the different macros on Richard Heathfield's site.
Here's a different solution I thought of that uses sizeof, so it's
category 1:

#define swap(t,x,y) myswap(sizeof(t),(unsigned char*)&(x),(unsigned
char*)&(y))
void myswap(unsigned long a,unsigned char *b,unsigned char *c)
{
while (a--) {
*b ^= *c;
*c ^= *b;
*b++ ^= *c++;
}
}

Gregory Pietsch
 
S

Sam Dennis

Gregory said:
void myswap(unsigned long a,unsigned char *b,unsigned char *c)

Not size_t a?
{
while (a--) {
*b ^= *c;
*c ^= *b;
*b++ ^= *c++;
}
}

That's a really bad idea; not only does it fail to deal with the two
values being the same, but, should they share a single byte of their
respective representations, it has undesirable behaviour for the few
types where it's undefined at all.
 
G

Gregory Pietsch

Sam Dennis said:
Not size_t a?

It probably comes later on in K&R2, or was a brain cramp on my fault. ;-)
That's a really bad idea; not only does it fail to deal with the two
values being the same, but, should they share a single byte of their
respective representations, it has undesirable behaviour for the few
types where it's undefined at all.

Then how would you actually accomplish this?
 
S

Sam Dennis

Gregory said:
Then how would you actually accomplish this?

The same way as elsewhere in this thread (with intentional and
unintentional mistakes corrected): with a temporary variable.
 
G

Gregory Pietsch

Sam Dennis said:
The same way as elsewhere in this thread (with intentional and
unintentional mistakes corrected): with a temporary variable.

So here's what you're telling me:

If the areas pointed to by b and c overlap, I should use a temporary
variable to swap the contents of b and c:

void myswap(size_t a, unsigned char *b, unsigned char *c)
{
unsigned char uc;

if (a && b && c)
while (a--) {
uc = *b;
*b = *c;
*c = uc;
b++, c++;
}
}

My point is that if the two areas overlap, you can't swap no matter
what algorithm you use. (Think about it for a second.)

Gregory Pietsch
 
S

Sam Dennis

Gregory said:
Gregory Pietsch wrote:
void myswap(unsigned long a,unsigned char *b,unsigned char *c)
[xor bytewise]

That's a really bad idea;

So here's what you're telling me:

If the areas pointed to by b and c overlap, I should use a temporary
variable to swap the contents of b and c:

Where did you get that from? What I'm trying to say is that the xor
hack is unreliable under the best of circumstances and that applying
it to object representations (of an unknown type, no less) is asking
for trouble.

If you absolutely need a function of this sort (for swapping arrays,
or somesuch, I guess), it's probably most efficient to have a buffer
local to the function of a reasonable size for a loop of three calls
to memcpy, analogous to the three assignments in a swapping macro.

What the hell would swapping objects that overlap mean, anyway? It's
utter nonsense!
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top