Знаковый разряд расширяется. Если хотя бы одна из разностей отрицательная (т.е. числа различаются), >> sizeof(a)*8 даст в результате 0xFFFFFFFF.
Booster Код который я привел, я тестировал. Все прекрасно работает. Но не по предполагаемой мной причине, а потому что компилятору от MS без разницы что написано в исходном коде, оба варианта (>> sizeof(a)*8 и >> (sizeof(a)*8-1)) приводятся к виду sar reg, 31.
Код (Text): c = a&((signed)((a-b) | (b-a)) >> (sizeof(a)*8)); ... 1>.\test.cpp(10) : warning C4293: '>>' : shift count negative or too big, undefined behavior ... CPU Disasm Address Hex dump Command Comments 00401019 |. 8B4424 14 MOV EAX,DWORD PTR SS:[ESP+14] 0040101D |. 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10] 00401021 |. 8BD1 MOV EDX,ECX 00401023 |. 2BD0 SUB EDX,EAX 00401025 |. 8BF0 MOV ESI,EAX 00401027 |. 2BF1 SUB ESI,ECX 00401029 |. 0BD6 OR EDX,ESI 0040102B |. C1FA 1F SAR EDX,1F 0040102E |. 23D0 AND EDX,EAX
google Не знаю, что у тебя со студией или с кодом. У меня 2005 и 2010 генерят сдвиг на 32. Странно если бы было иначе. Код (Text): #include <iostream> int main (int argc, char* argv[]) { unsigned a = 3; unsigned b = 1; unsigned c = a&((signed)((a-b) | (b-a)) >> (sizeof(a)*8)); std::cout << c << std::endl; }
Опа, оно в дебаге генерит: Код (Text): unsigned c = a&((signed)((a-b) | (b-a)) >> (sizeof(a)*8)); 004113CC mov eax,dword ptr [a] 004113CF sub eax,dword ptr [b] 004113D2 mov ecx,dword ptr [b] 004113D5 sub ecx,dword ptr [a] 004113D8 or eax,ecx 004113DA sar eax,20h 004113DD and eax,dword ptr [a] 004113E0 mov dword ptr [c],eax В релизе: Код (Text): 00401000 mov eax,dword ptr [__imp_std::endl (402040h)] 00401005 mov ecx,dword ptr [__imp_std::cout (402044h)] 0040100B push eax 0040100C push 3 0040100E call dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (40203Ch)] 2005 без SP. Ну вы поняли, это типа UB, нужно (sizeof(a)*8 - 1)).
Booster Код из #34 у меня так же компилируется как в посте #35. Дабы избежать подобных оптимизаций в релизе я тестировал на таком коде: Код (Text): #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { unsigned a, b, c; _tscanf(__T("%d %d"), &a, &b); c = a&((signed)((a-b) | (b-a)) >> (sizeof(a)*8)); _tprintf(__T(%d\n"), c); return 0; } Тут получается сдвиг на 31, как ни странно.