Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 04.11.2017, 13:50   #1
goto ∞
Форумчанин
 
Аватар для goto ∞
 
Регистрация: 21.12.2010
Сообщений: 155
По умолчанию Си, побитовые операции.

Функция setbits(x, p , n, y) которая возвращает x, в котором n битов, начиная с позиции p, равный n крайним правым битам аргумента y, а остальные не трогать.
Например: set(x, 5, 4, y)
x = 1 0 1 0 1 1 0 1
y = 1 1 0 1 0 1 1 1
рез 1 0 0 1 1 1 0 1

Код:
#include <stdio.h>
 
unsigned setbit(unsigned x, int p, int n, unsigned y){
    return (((~0 << n) >> 8-p+1) ^ x) | ((y << 8-n) >> 8 - p + 1);
}
int main(){
    printf("%d", setbit(173, 5, 4, 215));
    return 0;
}
Результат функции -147 хотя мы возвращаем без знаковый тип данных. Почему так?

если пробуем переписать так:
Код:
...
return (((~0u << n) >> 8-p+1) ^ x) | ((y << 8-n) >> 8 - p + 1);
...
То так возвращает вообще другое число.
goto ∞ вне форума Ответить с цитированием
Старый 04.11.2017, 14:24   #2
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,695
По умолчанию

Потому что выводите вы его как знаковый. Прочитайте про спецификаторы принтфа.
p51x вне форума Ответить с цитированием
Старый 04.11.2017, 14:52   #3
goto ∞
Форумчанин
 
Аватар для goto ∞
 
Регистрация: 21.12.2010
Сообщений: 155
По умолчанию

Цитата:
Сообщение от p51x Посмотреть сообщение
Потому что выводите вы его как знаковый. Прочитайте про спецификаторы принтфа.
По книги я еще не знаю никаких спецификаторов кроме %d, %c, %f0x, %x, %s думаю проблема не тут. Я тут проверял каждый сдвиг сначала влево потом направо, оказывается биты сохраняются и при последующем сдвиге обратно они возвращаются, я то думал что все 0 должны быть ну или все 1. Тут алгоритм мой неправильный получается, тогда как он возвращает нужное число только с отрицательным знаком? Путаницы тут хватает.
goto ∞ вне форума Ответить с цитированием
Старый 04.11.2017, 16:23   #4
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Есть 2 вида сдвига. Круговой через перенос и как вы говорите. В С++ НЕ круговой, т.е. если сдвинуть 8битное целое на 8 - будет ноль.
Круговые нужно городить отдельно, например так:
Код:
 const auto static rol1 = [] (uint8_t x)->uint8_t
    {
        return static_cast<uint8_t>(((x >> 7) | (x << 1)));
    };

    const static auto rol = [](int8_t v, int bits)->int8_t
    {
        uint8_t tmp = static_cast<uint8_t>(v);
        for (int i = 0; i < bits; ++i)
            tmp = rol1(tmp);
        return static_cast<int8_t>(tmp);
    };
Компилятор это все соптимизирует в ассемблерную ROL.

А вообще перепроверьте 2 момента:
1. Все числа там int (знаковые), т.о. битовые операции над ними дадут знак тоже.
2. Порядок операций. Сдвиги лучше все в скобочки явно расставлять всегда. У них самый низкий приоритет.

Последний раз редактировалось alexzk; 04.11.2017 в 16:35.
alexzk вне форума Ответить с цитированием
Старый 04.11.2017, 16:33   #5
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

дел
alexzk вне форума Ответить с цитированием
Старый 04.11.2017, 17:26   #6
goto ∞
Форумчанин
 
Аватар для goto ∞
 
Регистрация: 21.12.2010
Сообщений: 155
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
Есть 2 вида сдвига. Круговой через перенос и как вы говорите. В С++ НЕ круговой, т.е. если сдвинуть 8битное целое на 8 - будет ноль.
Круговые нужно городить отдельно, например так:
Код:
 const auto static rol1 = [] (uint8_t x)->uint8_t
    {
        return static_cast<uint8_t>(((x >> 7) | (x << 1)));
    };

    const static auto rol = [](int8_t v, int bits)->int8_t
    {
        uint8_t tmp = static_cast<uint8_t>(v);
        for (int i = 0; i < bits; ++i)
            tmp = rol1(tmp);
        return static_cast<int8_t>(tmp);
    };
Компилятор это все соптимизирует в ассемблерную ROL.

А вообще перепроверьте 2 момента:
1. Все числа там int (знаковые), т.о. битовые операции над ними дадут знак тоже.
2. Порядок операций. Сдвиги лучше все в скобочки явно расставлять всегда. У них самый низкий приоритет.
Это вроде код на С++.
Я пришел к выводу что если переносить то только в одну сторону до конца
goto ∞ вне форума Ответить с цитированием
Старый 04.11.2017, 21:14   #7
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от goto ∞ Посмотреть сообщение
Это вроде код на С++.
Я пришел к выводу что если переносить то только в одну сторону до конца
Вопщем да, но битовые операции из этого кода - одинаковы.
alexzk вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Побитовые операции Ilai Помощь студентам 2 26.04.2015 17:38
Побитовые операции alexusankov C# (си шарп) 6 01.12.2013 22:38
Побитовые операции С++ Pein95 Общие вопросы C/C++ 3 19.11.2012 14:48
побитовые операции serega28 Паскаль, Turbo Pascal, PascalABC.NET 11 25.01.2011 14:02
побитовые операции Dimarik Общие вопросы C/C++ 7 16.04.2010 19:27