2015-06-27 2 views
-1

Тип size_t - это неподписанный тип. Таким образом, смещение вправо значения типа size_t будет логически изменяться. Учитывая, что ширина size_t зависит от реализации, существует ли способ правого сдвига а size_t значение арифметически?Арифметическое правое смещение значение size_t

Если моя цель - создать битовую маску из значения size_t, содержащего 1 или 0, есть ли другой способ сделать это? Для целых чисел с известными ширинами самый простой способ, которым я знаю, создать битовую маску, - это сдвиг влево по ширине целого числа - 1, а затем арифметический сдвиг вправо до конца.

Это работает на моем 64-битной системе:

const size_t width = (sizeof(size_t) << 3)) - 1; 
size_t value = {boolean value}; 
value = ((int64_t) (value << width)) >> width; 

Но, конечно, это относится исключительно к моей системе и системы, как это. Что я могу использовать вместо этого?

+0

Если я правильно понял, что вы хотите, то эффективно 'size_t mask = original? -1: 0; ', если« создавая маску из значения, содержащего 1 или 0 », вы имеете в виду расширение знака от 1 бит до того, сколько битов имеет размер' size_t'. –

+0

Да, в значительной степени. Часть меня хотела сделать это без тройного оператора. Но мне все еще любопытно, есть ли хороший способ сделать арифметическую правую смену. – skeggse

+1

Почему нисходящий, кто-нибудь? – skeggse

ответ

2

Ваш оригинальный код & hellip;

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

& hellip; может быть упрощена таким образом:

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

О да, отрицание делает это. Благодаря! – skeggse

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.

Любой хороший оптимизирующий компилятор для машины с арифметическим кодом операции правой смены должен признать, что две ветви идентичны для случаев, которые они обрабатывают, и полностью оптимизируют ветвь, производя единую операцию без ветвей.

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 является лучшим подходом здесь, но я решил опубликовать этот ответ, потому что вы проявили интерес к тому, как (а если) можно сделать арифметические сдвиги вправо на неподписанных типах.

+0

Спасибо! Мне было очень интересно узнать об общем случае (и, похоже, это был лучший вопрос). – skeggse

Смежные вопросы