эта, почему int x >> 32 == x?

yolki

*джекичанwhy?*

#include <stdio.h>
int main
{
int x=0xFF,i;
for(i=0;i<=32;i++)
{
printf("x=%08X shifted %d: %08X\n",x,i,x>>i);
}
return 100500;
}
$ ./a.out
x=000000FF shifted 0: 000000FF
x=000000FF shifted 1: 0000007F
x=000000FF shifted 2: 0000003F
...
x=000000FF shifted 6: 00000003
x=000000FF shifted 7: 00000001
x=000000FF shifted 8: 00000000
...
x=000000FF shifted 30: 00000000
x=000000FF shifted 31: 00000000
x=000000FF shifted 32: 000000FF

marat7256

А сделай еще на 33 и 64. Что будет? Просто любопытно.

tokuchu

А сделай еще на 33 и 64. Что будет? Просто любопытно.
У меня 33-40 получилось как 1-8. Может быть какая оптимизация в процессоре или даже фича, что смещение делается не на i, а на i & 31?

tokuchu

Если налево двигать, то такая же фигня. :)

VitMix

Не знаю, как в C/C++, но в Java (x >> y) эквивалентно (x >> (y & 31 если x типа int и (x >> (y & 63 если x типа long. То есть учитываются только 5 (6 для long) младших бит второго аргумента.

procenkotanya

Welcome to C and undefined behavior. Некоторые процессоры, в том числе x86, обрезают величину сдвига до логарифма размера слова в битах.

tokuchu

Welcome to C and undefined behavior. Некоторые процессоры, в том числе x86, обрезают величину сдвига до логарифма размера слова в битах.
Так причём здесь C? Вон даже в Java как фичу объявили.
Это процессор же так делает. Мы тут сейчас как минимум на AMD, Intel X86 и на каком-то Sun проверили.

margadon

и в ассемблерном листинге не видно хаков, это проц самолично

procenkotanya

В Java такой результат гарантируется (на любых процессорах, даже тех, которые сами не обрезают а в Си может быть что угодно. Может даже диск отформатироваться.

vall

Welcome to C and undefined behavior. Некоторые процессоры, в том числе x86, обрезают величину сдвига до логарифма размера слова в битах.
угу, причём так было не всегда. насколько я помню i386 двигал всё а 486 начал обрезать

tokuchu

В Java такой результат гарантируется (на любых процессорах, даже тех, которые сами не обрезают
Ну если у жабы такое в спецификации, то наверняка большинство процессоров так делает.
У кого-нибудь на ARM-ах каких-нибудь компилятор есть? Тоже было бы интересно как там.

procenkotanya

Ну если у жабы такое в спецификации, то наверняка большинство процессоров так делает.
У кого-нибудь на ARM-ах каких-нибудь компилятор есть? Тоже было бы интересно как там.
Армы обрезают до восьми бит, а не до пяти.

tokuchu

Армы обрезают до восьми бит, а не до пяти.
Интересно. Ну X86 тоже не обязательно до 5 бит обрезает. У меня для лонга до 6 обрезало.

Anturag

 
Ну если у жабы такое в спецификации, то наверняка большинство процессоров так делает.
У кого-нибудь на ARM-ах каких-нибудь компилятор есть? Тоже было бы интересно как там.
Армы обрезают до восьми бит, а не до пяти.
:собака-подозревака:
Если речь не про какой-нибудь arm64 (и уж тем более thumb а про 32-битный arm, то вообще-то до пяти, при этом для обсуждаемого lsr допустимые значения от 1 до 32 включительно. Иначе, прошу привести пример машинного кода инструкции "lsr r0, r0, #33".

procenkotanya

речь про случаи когда величина сдвига в регистре

Anturag

Да, тогда нет возражений, всё верно.

bleyman

Welcome to C and undefined behavior. Некоторые процессоры, в том числе x86, обрезают величину сдвига до логарифма размера слова в битах.

Я бы хотел заметить, что ты вносишь сумятицу в наивные мозги людей, как бы приравнивая undefined behaviour к unspecified behaviour.
Вношу ясность, подключаемся, работаем: в языках C и C++ всё поведение чотко определено, и есть три разных понятия:
1. implementation-defined behaviour: например, 4 == sizeof(int). Твой компилятор для твоей таргет платформы обязан определить это поведение и делать всегда так. Если твоя программа работает ОК с этим компилятором для этой платформы, она так и будет работать, но может перестать работать с другим компилятором/на другой платформе.
2. unspecified behaviour: например, порядок вычисления параметров функции. f(g h: если g и h делают какие-то глобально-видимые вещи, порядок деланья этих вещей может меняться между двумя последовательномыми вызовами "f(g h", и меняться ещё раз между разными компиляциями тем же самым компилятором, и вообще. Если порядок для тебя важен, то это баг в твоей программе. Читай про sequence points в стандарте.
3. undefined behaviour: например, integer overflow (also, overflowing shifts): ты может не знаешь, но ты подписался что ты никогда не будешь этого делать. Так что компилятор может фигачить код который работает правильно если undefined behaviour не происходит, и делает неведомую хуйню если он происходит. И даже тупо выкидывать код который триггерит undefined behaviour, например, if (x + y < x) любой вменяемый компилятор будет считать always false, и генерить код соответственно. Если тебе кажется что то, что ты компилишь под x86 где integer overflow будет вот так проявляться, тебе кажется неправильно, компилятор тупо выкинет эту проверку.

vall

хм, оно больше на undefined похоже. если сдвиг константный и вычислился при компиляции то 1<<32 gcc превращает в ноль (попутно кидая ворнинг) а если не константный то будет 1.

ppplva

Оно и есть undefined, потому что в стандарте так.
undershift (есть такой термин вообще?) знакового типа - implementation defined.
Оставить комментарий
Имя или ник:
Комментарий: