- 1
- 2
- 3
int rotate(int a, int k) {
return (a << k) | (a >> (32-k));
}
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+131
int rotate(int a, int k) {
return (a << k) | (a >> (32-k));
}
Вращение на k бит влево.
Так вот. В обоих случаях код будет работать корректно, несмотря на UB.
P.S. Да и кому в здравом уме надо вертеть регистр на 0 бит?
Sha-1?
А если он signed - то это и не вращение, а НЁХ из-за знакового расширения в >>.
Вывод: знаковые числа не нужны.
Обычный сдвиг — это умножение/деление на степени двойки. Сдвиг с расширением знака — для питухов, которым зачем-то нужны отрицательные числа.
А зачем нужен циклический сдвиг? Для доступа к разрядом битовых полей? Но ведь у нас есть bt/bsf/bsr.
Для криптовалок. Там почти в каждом алгоритме циклические сдвиги.
Во первых, одну, во вторых, константное время -> противодействие тайминговым атакам.
Это не жаба и не шарп. int в сишке может принимать любой размер.
http://govnokod.ru/13355#comment187236
13358
Ну разве нормально, что > и >> могут обозначать как знаковые (jg, sar), так и беззнаковые (ja, shr) операции?
Скажете, что операция выбирается исходя из типа аргументов? Во что скомпилируется?
Возможно, речь идет о "unsigned" ? Что-то я задумался.
На низких языках хорошо кодить в группе; одна голова хорошо, а несколько -лучше, если одна ошибется, другие исправят. А если кодишь один, то можно сильно извращаться(( это угнетает.
Одна голова ошиблась, остальные подхватили ошибку и понесли дальше. Им есть чем занятся, а не ваш гк править.
>>остальные подхватили ошибку и понесли дальше
Вот, может, пригодится.
http://ekowc.ru/assenization
Поменяю местами все двери дома )
Если бы ты игнорил меня с самого начала, а не кидал быдлореплики, было бы куда лучше, на будущее тебе.
Пардон, не удержался.
Даже сишка поддерживает основные виды абстракций:
- абстракция данных (forward declaration + функции-акцессоры)
- абстракция процедур (функции, принимающие на вход функции? пожалуйста. С возвратом функций сложнее, ибо замыканий нема, царские методы в продакшене не катят).
- разделение интерфейса и реализации (яркий пример - ядрёный vfs)
Синтаксическая абстракция в попе, но её вообще мало кто поддерживает. Тут у сишки скорее плюс, ибо богомерзкий препроцессор.
Ну а что руками писать приходится, это да. Зато можно выточить в точности такой велик, какой хочется. И контроля над производительностью больше.
Впрочем, немного утомляет.
А чем указатели не замыкания?
> И контроля над производительностью больше.
Дык никто не говорит, что это не нужно вообще никогда, просто очень редко. Меньшее количество граблей важнее.
Так это уже проблемы работы с памятью, я б сказал.
Из протокола:
Программист не сдал вовремя заказ, потому, что умер посреди разработки.
P/S.
Чего вы его минусуете? Он прав.
__rold(); Питухи О5 не осилили сишку. stdint.h - uint32_t.
unsigned long _lrotl(unsigned long, int);
И да, ни в C99, ни в C11 нет.
Такие же штуки в гцц есть для всех нормальных архитектур. Суть в том, что 95% их не юзают, да и не знают о них - вот я пролил свет на них.
Основной посыл был в stdint, а не __rold();
Да, в либц перечисленных функций нет, потому что они встроены в компилятор. Оно и логично: зачем линковать такую короткую функцию, когда её можно сделать инлайном?
_rotl, _rotr, _lrotl, _lrotr есть и у Микрософта, и у Борланда, и у Ваткома... Только одна проблема: при циклическом сдвиге нужно точно знать размер операнда, а в разных версиях сишки размер инта разный. Где восьми- и шестнадцатибитный циклический сдвиг, например? Можно, конечно, написать _rotl(x | (uint32_t)x << 16, k) & 0xffff, но такой код похож на говно, поэтому лучше будет (a << k) | (a >> (16-k)) в надежде, что gcc -O2 автоматически подставит ROL при правильном типе аргумента.
P.S. А как у гцц с поддержкой _rotl/_rotr на неинтеловских процессорах?
Это даже не функция гцц, а интринсики, которые должны быть к каждой архитектуре, которую держит конпелятор.
>Да, в либц перечисленных функций нет, потому что они встроены в компилятор. Оно и логично: зачем линковать такую короткую функцию, когда её можно сделать инлайном?
Щито ты несёшь - хедеры тоже часть либц - иди кури либц. Там половина функций инлайновые.
>Только одна проблема: при циклическом сдвиге нужно точно знать размер операнда, а в разных версиях сишки размер инта разный.
Если у тебя на x86( ты видишь там написанно x86intrin) инт 8байтный - твой конпелятор говно и выкинь его в форточку. Да и вообще, есть stdint, который маздайщики не осилили по причинет того, что их говноконпелятор не запилил с99.
>Где восьми- и шестнадцатибитный циклический сдвиг, например?
В питухе. Ты думаешь там просто так написанно __rold()? Там есть __rolb(), __rolw(), __rolq().
>Можно, конечно, написать _rotl(x | (uint32_t)x << 16, k) & 0xffff, но такой код похож на говно, поэтому лучше будет (a << k) | (a >> (16-k)) в надежде
Ты несёшь херню.
>что gcc -O2 автоматически подставит ROL при правильном типе аргумента.
Он итак подставит. На все из __rol*();
>P.S. А как у гцц с поддержкой _rotl/_rotr на неинтеловских процессорах?
#define _lrotl(a,b) __rolq((a), (b))
#define _lrotr(a,b) __rorq((a), (b))
Это тебе не питух.