Ответ на вопрос выше не так уж и прост на самом деле. Начнем с того, что когда вы запустите этот код на своей машине, то получите ответ: -1.
Эм. Неожиданно! "Как так получается?" - спросите вы меня. "Ведь я же знаю, как работает бинарный сдвиг: берем да и сдвигаем биты вправо и позади оставляем нули. В итоге получатся все нолики и самый младший бит 1. А это 1, а не -1!".
Логика железная и с ней не поспоришь. Однако в этой цепочке есть одно неверное утверждение. На самом деле вы не знаете, как работает правый бинарный сдвиг!(ну те, кто так рассуждают)
Заинтригованы?
Тогда мы идем к вам!
Что было до С++20.
Рассуждения верные только для беззнаковых чисел. Для знаковых все определяется конкретной реализацией. А у нас как раз такой вариант. Так еще все от стандарта зависит. Так что правильный ответ: "Мне-то откуда знать???". В общем случае вы вряд ли знаете, как во всех компиляторах это реализовано, а спрашивал я без привязки к конкретной реализации и стандарту. Да, вот так завуалировал ответ. Имею право.
Почему я тогда утверждаю, что вы на своих машинах получите -1?
Потому что в большинстве реализаций правый битовый сдвиг для знаковых чисел работает с помощью так называемого "арифметического сдвига".
Что это за акула такая.
Когда вы делаете правый сдвиг для беззнаковых чисел, то просто старшие разряды заполняете нулями. Арифметический же сдвиг заполняет старшие разряды не нулями, а знаковым битом. Таким образом, правый сдвиг любого 4-х байтного знакового числа оставит после себя либо 32 бита нулей (в случае положительного числа), либо 32 бита единичек(в случае отрицательного числа). А все единички в битах - это -1 для знаковых чисел.
С++20 начинает нам гарантировать, что правый сдвиг для знаковых чисел выполняется с помощью арифметического сдвига. Спасибо Дмитрию за это уточнение)
Вот такой прикол. Надеюсь, что я многих удивил тем, как это работает)
Арифметический сдвиг - хоть теперь и стандартное поведение, но
Во-первых, не все разрабы имеют достаточного опыта на 20-х плюсах, чтобы понять, что это стандартное поведение
Во-вторых, в каких-то проектах(которых на самом деле огромное количество) до сих пор не используется этот стандарт
В-третьих, слишком мало времени прошло с момента стандартизации. Если раньше это было грязным нестандартным приемом, то в умах людей он таковым еще долго останется. И это не изменится взмахом палочки комитета.
Поэтому не стоит использовать такие приколы без острой необходимости и правильного, подробного комментирования в случае этой необходимости.
Stay surprised. Stay cool.
#cpp20 #compiler
Эм. Неожиданно! "Как так получается?" - спросите вы меня. "Ведь я же знаю, как работает бинарный сдвиг: берем да и сдвигаем биты вправо и позади оставляем нули. В итоге получатся все нолики и самый младший бит 1. А это 1, а не -1!".
Логика железная и с ней не поспоришь. Однако в этой цепочке есть одно неверное утверждение. На самом деле вы не знаете, как работает правый бинарный сдвиг!(ну те, кто так рассуждают)
Заинтригованы?
Тогда мы идем к вам!
Что было до С++20.
Рассуждения верные только для беззнаковых чисел. Для знаковых все определяется конкретной реализацией. А у нас как раз такой вариант. Так еще все от стандарта зависит. Так что правильный ответ: "Мне-то откуда знать???". В общем случае вы вряд ли знаете, как во всех компиляторах это реализовано, а спрашивал я без привязки к конкретной реализации и стандарту. Да, вот так завуалировал ответ. Имею право.
Почему я тогда утверждаю, что вы на своих машинах получите -1?
Потому что в большинстве реализаций правый битовый сдвиг для знаковых чисел работает с помощью так называемого "арифметического сдвига".
Что это за акула такая.
Когда вы делаете правый сдвиг для беззнаковых чисел, то просто старшие разряды заполняете нулями. Арифметический же сдвиг заполняет старшие разряды не нулями, а знаковым битом. Таким образом, правый сдвиг любого 4-х байтного знакового числа оставит после себя либо 32 бита нулей (в случае положительного числа), либо 32 бита единичек(в случае отрицательного числа). А все единички в битах - это -1 для знаковых чисел.
С++20 начинает нам гарантировать, что правый сдвиг для знаковых чисел выполняется с помощью арифметического сдвига. Спасибо Дмитрию за это уточнение)
Вот такой прикол. Надеюсь, что я многих удивил тем, как это работает)
Арифметический сдвиг - хоть теперь и стандартное поведение, но
Во-первых, не все разрабы имеют достаточного опыта на 20-х плюсах, чтобы понять, что это стандартное поведение
Во-вторых, в каких-то проектах(которых на самом деле огромное количество) до сих пор не используется этот стандарт
В-третьих, слишком мало времени прошло с момента стандартизации. Если раньше это было грязным нестандартным приемом, то в умах людей он таковым еще долго останется. И это не изменится взмахом палочки комитета.
Поэтому не стоит использовать такие приколы без острой необходимости и правильного, подробного комментирования в случае этой необходимости.
Stay surprised. Stay cool.
#cpp20 #compiler