Wykonałem głupi test na temat manipulacji bitami i znalazłem ten problem. Wykonuję ten kod:Lewe bity zmiany w c
int main(){
unsigned int i;
for (i=1; i<34; i++)
{
unsigned long temp = i;
unsigned long mul = 1;
unsigned long val;
unsigned long one = 1;
// Way 1
while (temp--)
mul = mul << one;
// Way 2
val = (one<<i);
printf(" \n 1<<%i \n mul: 0x%X , val: 0x%X\n",i, mul, val);
}
}
Oczywiście wiem, że kiedy i> 31, zostanie wygenerowany przelew. Myślę, że obie części kodu (way1 i way2) powinny wyprowadzać ten sam wynik. Ale mam to (na końcu):
/* ... correct results from i=1 to i=31 ... */
1<<30
mul: 0x40000000 , val: 0x40000000
1<<31
mul: 0x80000000 , val: 0x80000000
1<<32
mul: **0x0** , val: **0x1**
1<<33
mul: **0x0** , val: **0x2**
Dlaczego, jeśli obie instrukcje są przesunięcia w lewo, program produkuje różne wyjścia? Wygląda na to, że część drogi2 tworzy okrągłą zmianę, ale nie wiem dlaczego, naprawdę uważam, że "mul" zawsze ma właściwą wartość.
skompilować pod maszyną Intel 32-bitową, wersja gcc 4.4.7
Wynik operacji zmiany z wartością przesunięcia większą niż szerokość operandy jest niezdefiniowana według standardu C. –
Po prostu opinię, ale powiedziałbym, że w tych przypadkach: 'mul << jeden' i' jeden << i', lepiej jest po prostu użyć '1' niż nadać mu nazwę" one ". –
To jest problem, tak. W tym przypadku najprawdopodobniej AND's prawy operand z 0x3F przed wykonaniem shft. –