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?
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.
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)))))
cast the shifted operand to the max possible width.
#define ROTL(X, N) (((uint64_t)(X) << (N)) | ((uint64_t)(X) >> (8 * sizeof(X) - (N))))
User contributions licensed under CC BY-SA 3.0