1

I am making a program that shifts values left or right depending on the value of the 2nd argument. If it is positive then it shifts left, else it shifts right. N is the number of times it shifts left or right. I am having trouble in implementation of my Macros.

#include <stdio.h>

#define SHIFT(value, n) 

#if (n) > 0
    (unsigned int value) <<= (int n);
#else 
    ( (unsigned int value)) >>= (int -n);



int main()
{
    printf("%d\n", SHIFT(1, 4));
} 

Currently I am getting a conditional directive error.

1
  • Try ` #define SHIFT(value, n) \ `. A backslash at the end indicates next line is part of current line. Commented Jan 6, 2014 at 9:58

3 Answers 3

6

The C preprocessor doesn't really work the way you intend to use it. In particular, you cannot use other CPP directives (like #if, ...) in the expansion of a macro. Besides, since macro expansion is a static compile-time feature, this wouldn't help anyway, when the actual shift-values are only known at run-time:

int value_to_shift = read_some_integer_from_user();
int amount_to_shift_by = read_another_integer_from_user();
int shifted_value = SHIFT(value_to_shift, amount_to_shift_by);

If you don't mind the potential double-evaluation of macro arguments, go with the ternary operator:

#define SHIFT(value, n)   ( (n) < 0? ((value) >> (-n)) : ((value) << (n)) )

Note, that using <<= (and >>=) as you do in the code is most likely not what you want, given, that you pass literal numbers as value arguments to your the SHIFT macro.

I would probably go for a tiny helper function here instead of a macro:

static int 
shift(int value, int nbits)
{
    return nbits < 0? (value >> -nbits) : (value << nbits);
}
Sign up to request clarification or add additional context in comments.

4 Comments

Okay. Is there any way to do this with using data types in arguments?
@XiJiaopin: And why do you want that?
It would be appropriate in this specific program which is derived from shifting with unsigned integers
@XiJiaopin -- In C++, you could use a template. In C, there is currently no way I could think of. Depending on your compiler, you might be able to cook something up using the mechanism used to implement the (type generic math)[en.cppreference.com/w/c/numeric/tgmath] stuff of C99. I haven't used that myself at all, and cannot tell, whether this would be a viable way at all.
1

Your #define isn't doing what you think it does. You need to continue the lines with \. And since n is known at runtime (assuming your case is just a simplification) you can use a regular function, and inline it if needed:

inline int shift(int value, int n) {
    if (n < 0) {
        return (unsigned int) value << n;
    }
    else {
         return (unsigned int) value << -n;
    }
}

1 Comment

Your cast syntax looks odd. Did you mean (unsigned int)value?
0

You need to combine the lines with a \. you also missed thed #endif

Inplace macro:

#define SHIFT(value, n)        \
     value = ((n) > 0)  ?      \
             value << (n) :    \
             value >> -(n)

Return shifted value:

#define SHIFT(value, n)        \
     ( ((n) > 0)  ?            \
             (value) << (n) :  \
             (value) >> -(n) )

1 Comment

I know that's why I wrote it wouldn't work. Better to remove it then.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.