LINUX.ORG.RU

Объясните сишную магию v2

 ,


2

4

В продолжение темы: Объясните сишную магию

Ковыряю сорцы Skia и наткнулся на такой забавный ужас (ссылка):

int fLastMoveToIndex = 5; // любое число
fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 * sizeof(fLastMoveToIndex) - 1);

Экспериментально удалось выяснить, что данный код меняет знак и отнимает 1 только если число положительное. Как он это делает - я даже знать не хочу.

Вопрос: что мешало написать банальный if, или хотя бы оставить комментарий? Типичное сишное какерство?

PS: производительно данного куска кода на погоду не влияет.

★★★★★

опять небось ради не зависящего от входных данных времени исполнения

anonymous
()

Ну так что?

Каков окончательный вердикт специалистов ЛОРа?

Правильно ли поступил программист, что использовал байтолюбство вместо условия в этом месте или нет?

EXL ★★★★★
()
Ответ на: комментарий от anonymous

Нет, чтобы разработка не влияла на Грету Тунберг

anonymous
()
Ответ на: комментарий от EXL

Каков окончательный вердикт специалистов ЛОРа?

А ты кто, горный пушной зверюга, не специалист? Или ты - ответственный начальник, умеющий делегировать ответственность?

anonymous
()

возможно это такой вариант написать за компилятор, странное другое: camelCase в Си

anonymous
()
Ответ на: комментарий от Stanson

Я и тернарные операторы не уважаю, когда они читабельности вредят и сложение с вычитанием если оно хреново написано. А что? Фигню можно как угодно писать, даже на брейнфаке.

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 1)
Ответ на: комментарий от byko3y

Яйцеголовых можно было бы нанять, только где их найти?

Проблема в том, что яйцеголовые куются сначала в институте, а потом на месте работы. Сами по себе они не растут. Ведь соблазн заговнокодить слишком велик. И когда поцаны в школе, подъезде, на вечеринке – говнокодят, то удержаться в стороне просто очень трудно.

kostyarin_ ★★
()
Ответ на: комментарий от peregrine

Я и тернарные операторы не уважаю, когда они читабельности вредят и сложение с вычитанием если оно хреново написано.

Да как они вредят читабельности-то я не понимаю? Совершенно очевидно что они значат и читаются точно так же, как сложение с вычитанием. Вообще никакой разницы.

Нет, конечно младшекласснику, который едва выучил сложение с вычитанием, всякое умножение и деление может и будет непонятно, но вроде как человеки обучаемые, и достаточно быстро, или я что-то пропустил?

А если в какого-нибудь Выгодского заглянуть? Тоже читабельность плохая - значков незнакомых много? Ну так может не стоит соваться в программизьм, если ты неспособен усвоить несколько элементарных операций не описанных в школьной программе?

Stanson ★★★★★
()
Ответ на: комментарий от peregrine

Я и тернарные операторы не уважаю

А особенно когда они вложеные в несколько уровней, с разлапистыми условиями, да под return-ом . Красота (нет) :)

SkyMaverick ★★★★★
()
Ответ на: комментарий от anonymous

В теории категорий есть двойственная категория. Это когда меняешь стрелки на обратные и получается такая же стройная обратная «теория», когда нравятся битовые операции и не условные переходы, и последующая интоксикация битовыми операциями.

В таком случае, возвращаясь к теме генетики, речь идёт о борьбе двух генов – условных переходов, и битовых операций. Могу сказать уверено, что ген битовых операций активируется после занятий арифметикой с фиксированной запятой. Где обычные плюсы и минусы не катят вообще.

Но у человека не бывает полного доминирования. Поэтому условные переходы существуют на ряду с битовыми операциями. Это генетика. Генетический алгоритм выживания наиболее успешных кодеров.

kostyarin_ ★★
()
Ответ на: комментарий от SkyMaverick

А особенно когда они вложеные в несколько уровней, с разлапистыми условиями, да под return-ом . Красота (нет) :)

В Rust-е нормальный тренарник

let variable = if zbs { returnMe } else {  notMe };

Насчёт вложенности не особо знаю как там дела обстоят.

kostyarin_ ★★
()
Ответ на: комментарий от kostyarin_

В Rust-е нормальный тренарник

Ну нормально, как по мне. Я вот про вот такое что-нибудь

int FnName (void) {
  ...;
  return (A)? (B)? <лапша1>: <лапша2> :
              (С)? <лапша3>: <лапша4>;
}

И фиг пойми слёту что она должна вернуть, если условия ABC хоть сколько-нибудь нетривиальные. Это я ещё немного вложил и хоть слегка причесал форматирование.

SkyMaverick ★★★★★
()
Ответ на: комментарий от fsb4000

Единственный нормальный коммент в этом треде. Причем сразу убивает все лалакания здешних «специалистов» по бинарным операциям.

hotpil ★★★★
()
Ответ на: комментарий от fsb4000

Единственный нормальный коммент в этом треде. Причем сразу убивает все лалакания здешних «специалистов» по тернарным операциям.

anonymous
()
Ответ на: комментарий от fsb4000

https://quick-bench.com

Не знаю что он измеряет, потому что он у меня просто не работает, требует разрешить какие-то воркеры.

Но gcc генерит почти одинаковый код, только поменялось место not eax

https://godbolt.org/z/rnYzK5

anonymous
()
Ответ на: комментарий от anonymous

Да. сейчас ещё раз посмотрел, для X86-64 там одинаковый код.

наверное в первый раз я какой-то другой компилятор выбрал по ошибке.

Сейчас ещё по-выбирал специально arm и mips, там по разному бывает:

https://godbolt.org/z/nn1ase

https://godbolt.org/z/Yefo5c

https://godbolt.org/z/Wf6M44

fsb4000 ★★★★★
()
Ответ на: комментарий от fsb4000

Сейчас ещё по-выбирал специально arm и mips, там по разному бывает:

Жесть, что-то плохое творится внутри gcc. Неужели вся оптимизация переложена на кодогенератор и его кривизну? Clang более более однозначен.

anonymous
()
Ответ на: комментарий от fsb4000

ты -OFast случайно включил. но даже с -О2 благодатные биты на 10% быстрее. а что это за опция кто-то знает? у меня такой нет.

anonymous
()
Ответ на: комментарий от anonymous

ну просто на арме нет тех же инструкций которые есть на х86, поэтому компилятор не может сгенерить такой же код - он не запустится.

anonymous
()
Ответ на: комментарий от anonymous

вообще такое ощущение как будто вы бухими в этот тред пишете.

anonymous
()
Ответ на: комментарий от anonymous

компилятор не может сгенерить такой же код

Исходный код функций логически одинаков. Clang это видит и генерит одинаковый код. Gcc сперва генерит код, потом оптимизирует (я так предполагаю). Из-за чего оптимизирующие способности gcc зависят от качества кодогенератора.

anonymous
()
Ответ на: комментарий от anonymous

но даже с -О2 благодатные биты на 10% быстрее

И это имело бы смысл, если это горячая функция. В остальных случаях усложнение кода ради десятка машинных тактов и одной, если повезёт, наносекуды неоправдано. upd. К тому же, как мы видим из дизасма, кодогенератор и сам справляется с оптимизацией.

SkyMaverick ★★★★★
()
Последнее исправление: SkyMaverick (всего исправлений: 1)
Ответ на: комментарий от anonymous

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

это абсолютно нормально, что под разное железо код генерируется по-разному, так и должно быть.

anonymous
()
Ответ на: комментарий от SkyMaverick

ты делаешь выводы на основании комментария человека который осилил всего одну строку кода. тот же приём используется в других местах. у тебя же работает поиск в браузере, вбей эту строку в поиск и посмотри где она используется.

anonymous
()
Ответ на: комментарий от anonymous

нет, он не логически одинаков

Эти функции логически одинаковы с точки зрения виртуальной машины языка.

Почему эти одинаковые функции генерятся в разный код для одного и того же процессора? - это вопрос к компилятору.

anonymous
()
Ответ на: комментарий от SkyMaverick

да ладно, там же не тысячи операндов в условии, было б с чего дёргаться

Harald ★★★★★
()
Ответ на: комментарий от anonymous

у языка нет виртуальной машины. абстрактная машина - это какое-то кококо академистов, в си и с++ программа всегда выполняется на целевом железе и оптимизируется для целевого железа (даже если оно виртуальное).

под одно железо компилятор посчитал, что для if выгоднее сгенерировать такой код, под другое железо, что выгоднее сделать оптимизацию. почему он так считает - это другой вопрос. возможно, что по совокупности факторов, на арме принято предпочитать определённую инструкцию, потому что в 99% случаев это лучше чем альтернативы, может какие-то оптимизации не реализованы или отключены.

если бы это было не так, то это было бы серьёзное ограничение компилятора.

anonymous
()

Отсутствие ветвления

mittorn ★★★★★
()
Ответ на: комментарий от anonymous

Я это делаю не на основании поста RazrFalcon-а, а на основании следования правилу: «код должен быть максимально простым и понятным и для любого его усложнения должно быть разумное обоснование». В данном случае - это усложнение кода без обоснования (трюкачество, проще говоря) и не важно, где ещё используется этот приём.

SkyMaverick ★★★★★
()
Ответ на: комментарий от anonymous

абстрактная машина

В стандарте языка с++ есть абстрактная машина.

под одно железо … под другое железо …

Опять про разное железо. Откуда ты взял разное железо?

Железо одно. Функции выполняют эквивалентную (и тривиальную) логику. Компилятор генерит для них разный код. Это «кривость» компилятора.

anonymous
()
Ответ на: комментарий от anonymous

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

x * 2 и x << 1 - это не логически эквивалентные выражения. просто компилятор знает, что арифметический результат обоих выражений будет одинаковым и может заменить одно на другое если посчитает нужным. а если не посчитает нужным, то может и не заменить.

anonymous
()
Ответ на: комментарий от EXL

Каков окончательный вердикт специалистов ЛОРа?

Советская ЛОР-а врагу сказала - НЕТ.
anonymous
()
Ответ на: комментарий от anonymous

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

У языка должен быть мир, где он имеет смысл. Без асбтрактной машины, задающей смысл для конструкций языка, язык - это просто набор правильно построенных строк, не задающий никакого поведения.

x * 2 и x << 1 - это не логически эквивалентные выражения

Для некоторых конкретных типов это логически эквивалентные выражения. То, что оптимизирующий компилятор не видит эквивалентные более оптимальные выражения - это «кривизна» компилятора. И эти оптимизации можно делать на уровне языка, то есть эти оптимизации должны быть платформо-независимыми. То есть одинаковость должна быть на всех платформах: однаковые функции для x86 должны быть одинаковы для avr.

anonymous
()

Объясните сишную магию v2

Магия - колдовство.

anonymous
()
Ответ на: комментарий от RazrFalcon

Он хочет сказать, что ты хорошо набросил, скорее всего неосознанно, чем осознанно.

anonymous
()
Ответ на: комментарий от RazrFalcon

Экспериментально удалось выяснить

что мешало написать банальный if

хотя бы оставить комментарий?

#if 0
    if (fLastMoveToIndex >= 0) {
        fLastMoveToIndex = ~fLastMoveToIndex;
    }
#else
    fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 * sizeof(fLastMoveToIndex) - 1);
#endif

Рука-лицо.

WitcherGeralt ★★
()
Ответ на: комментарий от Stanson

сдвигом, исключающим или

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

thunar ★★★★★
()
Ответ на: комментарий от SkyMaverick

Если выражения поместить в скобки, то будет читаемо.

thunar ★★★★★
()
Ответ на: комментарий от anonymous

памоему тут ub, связанное со сдвигом знакового

Это «implementation defined», но компиляторы в данном случае стараются делать арифметический сдвиг.

byko3y ★★★★
()
Ответ на: комментарий от anonymous

нет, не будет такого. программу пишет программист, а не компилятор. машина не должна быть умнее человека, а если она умнее, то человек просто очень тупой.

это всё уже было 25 лет назад в джаве и джава доказала, что получается плохо. если ты хочешь откатиться на 25 лет назад, то ты конечно можешь это сделать, но это будет процесс обратный прогрессу.

если тебе нужен яп который оперирует логическими выражениями - посмотри на пролог, это примерно то, что ты описываешь.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.