1

In C, I want to create such a macro function that puts the content of the first argument into the second, the content of the second into the third and the content of the third into the first. The code below does it without macro:

void circ2 ( int *a, int *b, int *c ){
    int temp1;
    int temp2;
    int temp3;
    temp1 = *a;
    temp2 = *b;
    temp3 = *c; 
    *a = temp3;
    *b = temp1;
    *c = temp2;
    //printf( "%d\n%d\n%d\n", a, b, c );
}

int main(){
    int x;
    int y;
    int z;
    x = 1;
    y = 2;
    z = 3;

    //circ(a, b, c);
    circ(x, y, z);
    printf( "%d\n%d\n%d\n", x, y, z );
    return 0;
}

And the macro function that I tried to create:

#define temporary
#define temporary2
#define temporary3
#define circ(x, y, z) (x != y && x != z && y != z) ? temporary = x, temporary2 = y, temporary3 = z, y = temporary, z = temporary2, x = temporary3 : x, y, z

But I get the following error:

error: expected expression before ‘=’ token

Where am I making a mistake?

Göksenin Cakir
  • 186
  • 1
  • 3
  • 9
  • 2
    Doing #define temporary just defines that for the preprocessor not at runtime. So after the defines are inserted you have something like (...) ? = x, = y, = z : x,y,z – Davis Yoshida Jan 18 '15 at 00:15
  • 2
    Off-topic: That's a lot of temporaries. You could just do: `tmp = *a; *a = *b; *b = *c; *c = tmp;` (Of course, as your macro solution indicates, this won't work if two of a, b and c are the same pointer.) – rici Jan 18 '15 at 01:54

4 Answers4

3

temporary, temporary2, and temporary3 are defined, but you haven't supplied the values they're supposed to expand to, so the result of the macro expansion will look like

(x != y && x != z && y != z) ? = x, = y, = z (et cetera)

If you know the macro arguments will have type int, you could make your macro expand into a code block, like this:

#include <stdio.h>

#define circ(x,y,z) {int tmp=z; z=y; y=x; x=tmp; }

int main()
{
   int a=1, b=2, c=3;
   circ(a,b,c);
   printf("a=%d, b=%d, c=%d\n",a,b,c);
}

Output:

a=3, b=1, c=2

Jim Lewis
  • 43,505
  • 7
  • 82
  • 96
3

A small error in your non-macro code: The arguments to circ() need to be pointers. (I tried to edit, but it's under the 6-character limit.) The call should be:

    circ(&x, &y, &z); 

The permutation needs to be executable code, but does not need conditional execution. Try something like:

#define circ3(x, y, z) {int circ3__temp__=x; x = y; y = z; z = circ3__temp___;}

That will generate the code to permute three int values, with a local variable inside the braced block. The code is generated inline, and the oddball name for the temporary variable is an attempt to not duplicate any names used in the calling scope.

Beware that this will NOT behave like an expression when used with if, for, etc. controlling an expression statement. For example

if (condition)
    circ3(a,b,c); /* semicolon here causes problem */
else /* "else without if" error here is that problem */
    circ3(x,y,z);

So, it's not a perfect drop-in for a void function call. You need to remove the ; on the call, or put {} braces around the macro call.

Mike Housky
  • 3,959
  • 1
  • 17
  • 31
  • 2
    Using the `do{...}while(0)` pattern will allow you to invoke the macro from a one-line if statement. See this question: http://stackoverflow.com/questions/923822/whats-the-use-of-do-while0-when-we-define-a-macro. – Arthur Laks Jan 18 '15 at 04:05
  • 1
    @ArthurLaks Thanks for that. It's twisted, but nice! – Mike Housky Jan 18 '15 at 05:17
2

I suspect that the problem is that temporary, temporary2, etc. are undeclared. You might want to make your macro span multiple statements, separated by semicolons, instead of using the comma operator.

Arthur Laks
  • 524
  • 4
  • 8
2

When you write:

#define temporary

you are saying to the C preprocessor that "temporary" is defined, and it must be replaced by nothing. So when you write:

#define circ(x,y,z) (x != y && x != z && y != z) ? temporary = x, temporary2 = y, temporary3 = z, y = temporary, z = temporary2, x = temporary3 : x, y, z
circ(a,b,c)

Preprocessor will replace circ(a,b,c) by:

(a != b && a != c && b != c) ?  = x, = y, = z, y = , z = , x = : x, y, z

and C compiler does not understand it.

Hope this helps:

#define circ(x, y, z) do{int w;w=z;z=y;y=x;x=w;}while(0)