如何将字节数组中的所有位向左/向右旋转一定量

发布于 2025-01-20 15:09:56 字数 752 浏览 3 评论 0原文

I can rotate a word to left or right by a certain amount like this:

#define ROR(x, r) ((x >> r) | (x << (64 - r)))
#define ROL(x, r) ((x << r) | (x >> (64 - r)))

[...]

ROR(var1, 11);
ROL(var1, 11);

How can I do the same but with an entire array of bytes (I mean: all the bits in array sequence)? An array like this:

uint32_t somearray[12] = {
    0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
    0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
};

PS: There is a similar question here, but I需要知道如何用一定的数量进行操作。

I can rotate a word to left or right by a certain amount like this:

#define ROR(x, r) ((x >> r) | (x << (64 - r)))
#define ROL(x, r) ((x << r) | (x >> (64 - r)))

[...]

ROR(var1, 11);
ROL(var1, 11);

How can I do the same but with an entire array of bytes (I mean: all the bits in array sequence)? An array like this:

uint32_t somearray[12] = {
    0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
    0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
};

PS: There is a similar question here, but I need to know how to do it with some amount.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

葬シ愛 2025-01-27 15:09:56

rorrol宏:

  • 宏假设参数xuint64_t
  • UINT64_T转换为64位置的行为不确定。如果偏移数量r可以为null,则应修改表达式以避免转移64。
  • 宏参数应在扩展中进行括号,以避免优先问题。

这是一个修改版本:

// assuming x is a uint64_t and r in the range 0..63
#define ROR64(x, n) (((x) >> (n)) | ((x) << (63 - (n)) << 1))
#define ROL64(x, n) (((x) << (n)) | ((x) >> (63 - (n)) >> 1))

请注意,建议使用内联函数而不是宏来避免具有副作用和强制操作数的操作数问题:

// assuming r in the range 0..63
static inline uint64_t ror64(uint64_t x, int n) {
    return (x >> n) | (x << (63 - n) << 1);
}
static inline uint64_t rol64(uint64_t x, int n) {
    return (x << n) | (x >> (63 - n) >> 1);
}

要旋转一个完整的单词,将其他不同的数组用作源更容易和目的地并编写一个循环:

void ror32_array(uint32_t *dst, const uint32_t *src, size_t size, size_t n) {
    size_t dist = n / 32 % size;
    int shift = n % 32;
    for (size_t i = 0; i < size; i++) {
        dst[(i + dist) % size] = src[i] >> shift;
    }
    if (shift) {
        for (size_t i = 0; i < size; i++) {
            dst[(i + dist + 1) % size] |= src[i] << (32 - shift);
        }
    }
}

void rol32_array(uint32_t *dst, const uint32_t *src, size_t size, size_t n) {
    size_t dist = n / 32 % size;
    int shift = n % 32;
    for (size_t i = 0; i < size; i++) {
        dst[(i + size - dist) % size] = src[i] << shift;
    }
    if (shift) {
        for (size_t i = 0; i < size; i++) {
            dst[(i + size - dist - 1) % size] |= src[i] >> (32 - shift);
        }
    }
}

这是一个测试程序:

#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

[...]


void print(const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    while (*fmt) {
        if (*fmt == '%') {
            if (fmt[1] == 'd') {
                printf("%d", va_arg(ap, int));
                fmt += 2;
                continue;
            } else
            if (fmt[1] == 'p') {
                const uint32_t *src = va_arg(ap, uint32_t *);
                size_t size = va_arg(ap, size_t);
                for (size_t i = 0; i < size; i++) {
                    printf("%08lX%c", (long)src[i], " "[i + 1 == size]);
                }
                fmt += 2;
                continue;
            }
        }
        putchar(*fmt++);
    }
    va_end(ap);
}

int main() {
    uint32_t array[] = { 0, 1, 2, 4, 8, 16 };
    size_t size = sizeof(array) / sizeof(*array);
    uint32_t dest_array[size];
    int i, n, shift[] = { 0, 1, 2, 3, 8, 15, 24, 32, 48, 64, -1 };

    print("array = { %p }\n", array, size);
    for (i = 0; (n = shift[i]) >= 0; i++) {
        ror32_array(dest_array, array, size, n);
        memcpy(array, dest_array, sizeof(array));
        print("ror(array, %d) = { %p }\n", n, array, size);
    }
    while ((n = shift[--i]) != 0) {
        rol32_array(dest_array, array, size, n);
        memcpy(array, dest_array, sizeof(array));
        print("rol(array, %d) = { %p }\n", n, array, size);
    }
    return 0;
}

There are 2 problems with the ROR and ROL macros:

  • the macro assumes that the argument x is a uint64_t.
  • shifting a uint64_t by 64 positions has undefined behavior. If the number of shifts r can be null, you should modify the expression to avoid shifting by 64.
  • the macro arguments should be parenthesized in the expansion to avoid precedence issues.

Here is a modified version:

// assuming x is a uint64_t and r in the range 0..63
#define ROR64(x, n) (((x) >> (n)) | ((x) << (63 - (n)) << 1))
#define ROL64(x, n) (((x) << (n)) | ((x) >> (63 - (n)) >> 1))

Note that it is recommended to use inline functions instead of macros to avoid problems with operands with side effects and enforce operand sizes:

// assuming r in the range 0..63
static inline uint64_t ror64(uint64_t x, int n) {
    return (x >> n) | (x << (63 - n) << 1);
}
static inline uint64_t rol64(uint64_t x, int n) {
    return (x << n) | (x >> (63 - n) >> 1);
}

To rotate a full array of words, it is simpler to use a different array as the source and destination and write a loop:

void ror32_array(uint32_t *dst, const uint32_t *src, size_t size, size_t n) {
    size_t dist = n / 32 % size;
    int shift = n % 32;
    for (size_t i = 0; i < size; i++) {
        dst[(i + dist) % size] = src[i] >> shift;
    }
    if (shift) {
        for (size_t i = 0; i < size; i++) {
            dst[(i + dist + 1) % size] |= src[i] << (32 - shift);
        }
    }
}

void rol32_array(uint32_t *dst, const uint32_t *src, size_t size, size_t n) {
    size_t dist = n / 32 % size;
    int shift = n % 32;
    for (size_t i = 0; i < size; i++) {
        dst[(i + size - dist) % size] = src[i] << shift;
    }
    if (shift) {
        for (size_t i = 0; i < size; i++) {
            dst[(i + size - dist - 1) % size] |= src[i] >> (32 - shift);
        }
    }
}

Here is a test program:

#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

[...]


void print(const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    while (*fmt) {
        if (*fmt == '%') {
            if (fmt[1] == 'd') {
                printf("%d", va_arg(ap, int));
                fmt += 2;
                continue;
            } else
            if (fmt[1] == 'p') {
                const uint32_t *src = va_arg(ap, uint32_t *);
                size_t size = va_arg(ap, size_t);
                for (size_t i = 0; i < size; i++) {
                    printf("%08lX%c", (long)src[i], " "[i + 1 == size]);
                }
                fmt += 2;
                continue;
            }
        }
        putchar(*fmt++);
    }
    va_end(ap);
}

int main() {
    uint32_t array[] = { 0, 1, 2, 4, 8, 16 };
    size_t size = sizeof(array) / sizeof(*array);
    uint32_t dest_array[size];
    int i, n, shift[] = { 0, 1, 2, 3, 8, 15, 24, 32, 48, 64, -1 };

    print("array = { %p }\n", array, size);
    for (i = 0; (n = shift[i]) >= 0; i++) {
        ror32_array(dest_array, array, size, n);
        memcpy(array, dest_array, sizeof(array));
        print("ror(array, %d) = { %p }\n", n, array, size);
    }
    while ((n = shift[--i]) != 0) {
        rol32_array(dest_array, array, size, n);
        memcpy(array, dest_array, sizeof(array));
        print("rol(array, %d) = { %p }\n", n, array, size);
    }
    return 0;
}
冷血 2025-01-27 15:09:56

要旋转 array 中的所有位,请创建一个函数,该函数占用大小,指向数据的指针和移位量。

void rotate_right(size_t sz, void *a, unsigned shift);
#define ROR_ARRAY(a, sh) rotate_right((sizeof (a)), (a), (sh))

对于32位值的数组,数组的位移动可能与some_32_bit&gt;&gt; SH由于endian。与_Generic对宏的更先进的使用解决。

To rotate all the bits in an array, create a function that takes a size, a pointer to the data, and a shift amount.

void rotate_right(size_t sz, void *a, unsigned shift);
#define ROR_ARRAY(a, sh) rotate_right((sizeof (a)), (a), (sh))

For an array of 32-bit values, the bit shift of the array may be be the same arithmetically as some_32_bit >> sh due to endian. More advanced use of macros with _Generic solve solve that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文