我想为二进制旋转创建宏。
我的目标是使这些宏对于uint32_t
和uint64_t
操作数类型都是通用的。
我来到了这个实现:
#define ROTL(X, N) (((X) << (N)) | ((X) >> (8 * sizeof(X) - (N))))
#define ROTR(X, N) (((X) >> (N)) | ((X) << (8 * sizeof(X) - (N))))
这些宏可以正常工作,但是gcc
编译器在编译期间会发出警告:
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))))
我知道编译器抱怨X
和N
类型之间可能不匹配。但是即使我同时投射X
和N
,也会产生警告:
ROTL((uint32_t)0xdeadbeef, (uint32_t)0U);
我该怎么做才能以正确的方式消除这些警告?
答案 0 :(得分:3)
当第二个参数为零或大于第一个参数的位数时,您会遇到一些问题。您可以尝试使用该模块摆脱此问题。通过以下简单示例,这似乎可行:
#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;
}
我使用了CHAR_BIT
的{{1}}和limits.h
的{{1}}和UINT32_C
。您可以PRIX32
自己进行调整以执行相同的操作。
答案 1 :(得分:2)
仅当第二个参数为零时,您才收到警告。因此,如果N == 0
:
#define ROTL(X, N) ((N) == 0 ? (X) : (((X) << (N)) | ((X) >> (8 * sizeof(X) - (N)))))
答案 2 :(得分:0)
将移位后的操作数投射到最大可能宽度。
#define ROTL(X, N) (((uint64_t)(X) << (N)) | ((uint64_t)(X) >> (8 * sizeof(X) - (N))))