Proper way for declaring binary rotation preprocessor macro

2

I would like to create macros for binary rotations. My goal was to make those macros universal for both uint32_t and uint64_t operand types.

I came to this implementation:

#define ROTL(X, N)  (((X) << (N)) | ((X) >> (8 * sizeof(X) - (N))))
#define ROTR(X, N)  (((X) >> (N)) | ((X) << (8 * sizeof(X) - (N))))

Those macros work fine but gcc compiler produces warnings during compilation:

warning: right shift count >= width of type [enabled by default]
#define ROTL(X, N)  (((X) << (N)) | ((X) >> (8 * sizeof(X) - (N))))

warning: left shift count >= width of type [enabled by default]
#define ROTL(X, N)  (((X) << (N)) | ((X) >> (8 * sizeof(X) - (N))))

I know that compiler is complaining about possible mismatch between type of X and N. But warnings are produced even when I cast both X and N:

ROTL((uint32_t)0xdeadbeef, (uint32_t)0U);

What can I do to get rid of these warning the proper way?

c
gcc
macros
binary
bit-manipulation
asked on Stack Overflow Oct 2, 2018 by Klepak • edited Oct 8, 2018 by ReAl

3 Answers

3

You get some problems when the second argument is zero or greater then the number of bits of the first argument. You may try to use the module to get rid of this problem. This seems to work, with this simple example:

#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
#include <limits.h>

#define ROTL(X, N) \
    (((X) << ((N) % (CHAR_BIT * sizeof(X)))) | \
     ((X) >> ((CHAR_BIT * sizeof(X) - (N)) % (CHAR_BIT * sizeof(X)))))

int main() {
    for (int i = 0; i < 100; i++) {
        uint32_t a = ROTL(UINT32_C(0xdeadbeef), i);
        printf("%d\t%"PRIX32"\n", i, a);
    }
    return 0;
}

I've used CHAR_BIT from limits.h and UINT32_C and PRIX32 from inttypes.h. You may adjust by yourself ROTR to do the same.

answered on Stack Overflow Oct 2, 2018 by Giovanni Cerretani • edited Oct 2, 2018 by chux - Reinstate Monica
2

You get a warning only when the second argument is zero. So, just do nothing if N == 0:

#define ROTL(X, N)  ((N) == 0 ? (X) : (((X) << (N)) | ((X) >> (8 * sizeof(X) - (N)))))
answered on Stack Overflow Oct 2, 2018 by ReAl • edited Oct 2, 2018 by Giovanni Cerretani
0

cast the shifted operand to the max possible width.

#define ROTL(X, N)  (((uint64_t)(X) << (N)) | ((uint64_t)(X) >> (8 * sizeof(X) - (N))))
answered on Stack Overflow Oct 2, 2018 by P__J__ • edited Oct 2, 2018 by P__J__

User contributions licensed under CC BY-SA 3.0