leofun01 написав:Знайшов в доках опис того як працює operator >> :
microsoft.com написав:Якщо тип x є int або uint, зміщеня визначають 5 наймолодших бітів правого операнда. Тобто результат зміщеня такий як з count & 0x1F (або count & 0b_1_1111).
Якщо тип x є long або ulong, зміщеня визначають 6 наймолодших бітів правого операнда. Тобто результат зміщеня такий як з count & 0x3F (або count & 0b_11_1111).
.. що ж .. це повністю ламає основну логіку (з переповненям) і ламає логіку з циклами.
Це все сховане в глибинах архітектури.
Ну а також в компіляторі та увімкненій оптимізації — буде залежність від того, "32" прийшло у вираз як константа/змінна з "відомим" компілятору станом, чи через змінну якимсь способом, який компілятор не може проаналізувати, тобто замість асемблерної команди з константою для числа зсуву буде команда з числом у регістрі (*CX для x86*).
Для швидкого (однотактового) зсуву на довільне число в процесорах перед/у АЛП стоїть так званиий barrel shifter, що є оптимізованою групою мультиплексорів, які підключають біти виходу до потрібних бітів входу. Відповідно, 32-входові мультиплексори мають 5-входову адресу, на яку подаються 5 молодших бітів того регістра, який визначає зсув, а всі інші біти ігноруються. Ну або 5 бітів відповідного поля команди, якщо компілятор уоптимізував код, але тоді при зсуві на-більше-ніж він якраз у 0 і уоптимізує. І результат залежатиме від опцій оптимізації.
Нещодавно на роботі довелося все це пояснювати, коли у колег виникло запитання, чому MISRA лається на
#define MASK(n) ((1U << (n)) - 1U)
коли n прийшло як аргумент функції (а там де константа, там ніколи в коді 32 не було).
Навіть довелося код накатати, де у циклі виводилися результати двох зсувів, на некваліфікований лічильник циклу і на його копію у volatile-змінній.