0

I am trying to implement the standard xor swap algorithm as a C macro.

I have two versions of the macro. One that doesn't worry about the types and one that attempts to cast everything to an integer.

Here are the macro's

#define XOR_SWAP(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))

#define LVALUE_CAST(type,value) (*((type)*)&(value))
#define XOR_CAST_SWAP(type,a,b) (LVALUE_CAST((type),(a))=(type)(a)^(type)(b),LVALUE_CAST((type),(b))=(type)(b)^(type)(a),LVALUE_CAST((type),(a))=(type)(a)^(type)(b))

I know it's a pain to read the one with a cast, but your efforts are appreciated.

The error that I'm getting is:

some_file.c(260,3): expected expression before ')' token

Now, I'm looking at it but I still can't figure out where my problem lies.

I've even used the -save-temps option to capture the preprocessor output and the line looks like this:

((*(((intptr_t))*)&((Block1)))=(intptr_t)(Block1)^(intptr_t)(Block2),(*(((intptr_t))*)&((Block2)))=(intptr_t)(Block2)^(intptr_t)(Block1),(*(((intptr_t))*)&((Block1)))=(intptr_t)(Block1)^(intptr_t)(Block2)); 

Before anybody mentions it, I've since realized that I should probably make this a function instead of a macro. Or even better, just use that extra variable to do the swap, it isn't hard.

But I want to know why this macro doesn't work. The brackets seem to match exactly as I wanted them to, so why is it complaining?

The LVALUE_CAST is something I took from @Jens Gustedt's answer in this SO question.

Update:

The macro call that produces that preprocessor output looks like this:

XOR_CAST_SWAP(intptr_t, Block1, Block2);
Community
  • 1
  • 1
nonsensickle
  • 4,438
  • 2
  • 34
  • 61

1 Answers1

2

I don't believe you can wrap types in arbitrary levels of parentheses.* So this compiles fine:

((*(intptr_t*)&((Block1)))=(intptr_t)(Block1)^(intptr_t)(Block2),(*(intptr_t*)&((Block2)))=(intptr_t)(Block2)^(intptr_t)(Block1),(*(intptr_t*)&((Block1)))=(intptr_t)(Block1)^(intptr_t)(Block2));


* Disclaimer: this is purely empirical! I don't intend to peruse the standard to figure out what the details are...
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • You are correct, removing them did fix my issue. Thanks. I'm accepting the answer, but can I ask if you know of the actual reason why parenthesis have this effect on types? – nonsensickle Jul 04 '13 at 00:18
  • @nonsensical: I guess it's just the grammar of the C language that dictates this. – Oliver Charlesworth Jul 04 '13 at 00:19
  • 1
    @nonsensical Yep, parens simply don't appear for the grammar for *type-specifier* which is what `int` is, and is required by a *cast-expression*. The only place unlimited nesting is allowed in there appears to be around abstract-declarators, e.g. `(int(((((*)))))(void)) foo` casts to pointer to function type. – Potatoswatter Jul 04 '13 at 00:26
  • @Potatoswatter You're right. I was just looking up the grammar myself at http://www.cs.dartmouth.edu/~mckeeman/cs48/references/c.html and found the same, but I think that regular declarators also allow infinite parens. – nonsensickle Jul 04 '13 at 00:30
  • @nonsensical Yes, but a regular declarator can't go inside a cast-expression. – Potatoswatter Jul 04 '13 at 00:52