Sida 1 av 2

Fråga om >> i C

Postat: 25 april 2012, 16:25:39
av Kronberg
Vad betyder >> i följande rad?

t1 = ((long)t1*(long)volts) >> 15;

Har jag tolkat det rätt om t1 sätts till T1*volts enbart om värdet är större än 15, en förenklad version av en if-sats alltså?

Re: Fråga om >> i C

Postat: 25 april 2012, 16:28:25
av sodjan

Re: Fråga om >> i C

Postat: 25 april 2012, 16:36:57
av Kronberg
Det motsvarar alltså division med 32768.

Re: Fråga om >> i C

Postat: 25 april 2012, 16:39:42
av blueint
t1 multipliceras med volt och skiftas sedan binärt till höger (mindre värde) med 15 steg.

65536 >> 15 ger resultatet 2.

Om t1=10 000 och volt=12 så blir det först 120 000 som sedan skiftas 15 steg åt höger vilket ger resultatet 3.

Re: Fråga om >> i C

Postat: 25 april 2012, 16:40:55
av sodjan
Ja, om man tolkar det som skiftas som ett "värde".
Det kan ju vara något helt annat också. Men i exemplet
så ser det ju ut som att en uppmätt spänning ska skalas...

Re: Fråga om >> i C

Postat: 25 april 2012, 18:24:20
av cyr
Kan tilläggas att en anledning att man ofta använder shiftning när man ska dividera eller multiplicera med en faktor som är en jämn tvåpotens är att det är snabbare på många processorer (som saknar hårdvara för div och mul).

Re: Fråga om >> i C

Postat: 25 april 2012, 18:42:12
av sodjan
Speciellt på de som har en "barrel shifter" där antalet steg
som det ska shiftas är en parameter i shift-kommandot.
Alltså *en* 15-stegs shift istället för 15 1-stegs shift. Inte så
vanligt på 8-bitare, men på 16-bitars brukar de finna med.

Re: Fråga om >> i C

Postat: 25 april 2012, 19:28:23
av calmar
Ytterligare ett tillägg, moderna (nåja, hyffsat omoderna också ..) C-kompilatorer gör den här formen av optimering själva, det går alltså lika bra att skriva " / 32768" och få ut samma maskinkod. Som bonus blir koden mer lättläst och enklare att porta.

Re: Fråga om >> i C

Postat: 25 april 2012, 19:37:30
av Micke_s
En sak som kan förvirra här är hur unsigned och signed hanteras.

De flesta implementerar >> på en unsigned som logisk: dvs den fyller på med 0:or längst upp och >> som en logisk signed shiftar den ner men behåller tecknet(högsta bit:en bestämmer vad som ska fyllas ut med)

Re: Fråga om >> i C

Postat: 25 april 2012, 22:53:34
av Stalker
Vilket gör att höger shift inte är samma sak som division för negativa tal. Kompilatorn kan därmed inte optimera bort en division av signed så länge den inte samtidigt kan garantera att något fall där de skiljer åt inte kan inträffa.

Kod: Markera allt

{
	signed a=-1,b=-1;
	a /= 2;
	b >>= 1;
	// a == 0, b == -1 om implementerat som aritmetisk skift, men kan vara vad som helst
}

Re: Fråga om >> i C

Postat: 25 april 2012, 23:18:09
av sodjan
Kompilaton (och eventuellt processorn) måste kunna skilja på
en "logic shift" och en "arithmetic shift".

Re: Fråga om >> i C

Postat: 26 april 2012, 09:04:49
av jesse
hur ska den kunna skilja på det om det bara finns en symbol >> ?

I assembler finns det ju ofta två sorters shift åt höger (beror lite på processorfamilj):
Logic shift right och rotate right.

Logic shift lägger alltid i en nolla längst upp. Rotate lägger i värdet i carry-flaggan (och plockar värdet från lägsta biten och lägger i carry). I C finns det bara motsvarigheten för logic shift om man använder >> på ett "unsigned int". Detta motsvaras exakt av division med en tvåpotens. Alltså kan kompilatorn optimera detta.

Rotate finns givetvis inte då "carry" inte existerar i C.

Vad som däremot sker i ett "signed int" beror lite på kompilatorn, men de flesta verkar låta högsta biten ligga kvar oförändrad, viket ger ett resultat mycket nära division, men inte exakt. Det går att korrigera med lite villkor och ev. addition med ett - och på så vis kan man få en optimerad kod även när man ska dividera signed int med en tvåpotens.

Re: Fråga om >> i C

Postat: 26 april 2012, 09:55:38
av adent
Fast den borde ju kunna gå på om vänsteroperanden är unsigned eller inte. Vill man nu
Logical-shifta en signed får man cast:a till unsigned. och vice verca.

Re: Fråga om >> i C

Postat: 26 april 2012, 17:19:11
av jesse
hmmm.... jag har faktiskt inte tänkt på det förut, men kan shiftoperatorerna ( << och >> ) ta negativa tal på höger sida?

I så fall skulle 1 >> (-3) vara detsamma som 1 << 3 och resultatet blir 8.

Re: Fråga om >> i C

Postat: 26 april 2012, 18:21:33
av Stalker
Nej (generellt sett).
C99 avsnitt 6.3.7 Bitwise shift operators, punkt 3 skrev: If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.