算术右移大小_t值

时间:2015-06-27 19:09:12

标签: c bit-manipulation

size_t类型是无符号类型。因此,右移{type 1}}类型的值会在逻辑上发生变化。鉴于size_t的宽度是依赖于实现的,是否有任何方法可以算术右移size_t值?

如果我的目标是从包含size_tsize_t的{​​{1}}值创建位掩码,还有其他方法吗?对于具有已知宽度的整数,我知道制作位掩码的最简单方法是左移整数的宽度 - 1,然后算术右移一直向后移动。

这适用于我的64位系统:

1

但当然它特定于我的系统和系统。我可以用什么呢?

3 个答案:

答案 0 :(得分:2)

您的原始代码......

const size_t width = (sizeof(size_t) << 3)) - 1;
size_t inpvalue = {zero or one};
size_t outvalue = ((int64_t) (value << width)) >> width;

......可以通过这种方式简化:

size_t inpvalue = {zero or one};
size_t outvalue = -inpvalue;

答案 1 :(得分:1)

尝试这样的事情:

#define UNSIGNED_SRA(x,n) ((x)<=(0?(x):-1)/2 ? (x)>>(n) : ~(~(x)>>(n)))

表达式(0?(x):-1)/2计算出具有高位清除的x类型的最大值;如果您知道特定类型,例如size_t,则可以使用SIZE_MAX/2

对于具有算术右移操作码的机器,任何优秀的优化编译器都应该认识到两个分支对于它们处理的情况是相同的,并且完全优化分支,从而产生单个无分支操作。

答案 2 :(得分:1)

  

有没有办法在算术上右移一个size_t值?

是的,有。实际上,给定无符号类型的值v,我相信您可以按如下方式执行算术右移(size_t的示例):

v = (v >> 1U) | (v & ~(~(size_t) 0 >> 1U));

基本上,它执行逻辑右移,然后如果移位前的最高有效位为1,则将最高有效位设置为1.

这是一个小型玩具程序,可以进行一些测试:

#include <stdio.h>

void print_binary(size_t v) {
    size_t mask = ~(~(size_t) 0 >> 1U);
    while (mask) {
        putchar('0'+!!(v&mask));
        mask >>= 1U;
    }
    putchar('\n');
}

int main() {
    size_t v;

    // Some random number
    v = 5583705;
    print_binary(v);
    v = (v >> 1U) | (v & ~(~(size_t) 0 >> 1U));
    print_binary(v);

    v = ~(~(size_t) 0 >> 1U);
    print_binary(v);
    int i;
    for (i = 0; i < 10; i++) {
        v = (v >> 1U) | (v & ~(~(size_t) 0 >> 1U));
        print_binary(v);
    }   

    return 0;
}

在我的机器上打印:

0000000000000000000000000000000000000000010101010011001101011001
0000000000000000000000000000000000000000001010101001100110101100
1000000000000000000000000000000000000000000000000000000000000000
1100000000000000000000000000000000000000000000000000000000000000
1110000000000000000000000000000000000000000000000000000000000000
1111000000000000000000000000000000000000000000000000000000000000
1111100000000000000000000000000000000000000000000000000000000000
1111110000000000000000000000000000000000000000000000000000000000
1111111000000000000000000000000000000000000000000000000000000000
1111111100000000000000000000000000000000000000000000000000000000
1111111110000000000000000000000000000000000000000000000000000000
1111111111000000000000000000000000000000000000000000000000000000
1111111111100000000000000000000000000000000000000000000000000000

似乎工作正常。

对于你的具体问题,我相信dlask的答案是最好的方法,但我决定发布这个答案,因为你有兴趣知道如何(以及如果)可以对无符号进行算术右移类型。