Fråga om >> i C

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Kronberg
Inlägg: 154
Blev medlem: 9 april 2004, 18:51:29

Fråga om >> i C

Inlägg 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å?
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Fråga om >> i C

Inlägg av sodjan »

Kronberg
Inlägg: 154
Blev medlem: 9 april 2004, 18:51:29

Re: Fråga om >> i C

Inlägg av Kronberg »

Det motsvarar alltså division med 32768.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Fråga om >> i C

Inlägg 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.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Fråga om >> i C

Inlägg 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...
cyr
Inlägg: 2712
Blev medlem: 27 maj 2003, 16:02:39
Ort: linköping
Kontakt:

Re: Fråga om >> i C

Inlägg 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).
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Fråga om >> i C

Inlägg 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.
Användarvisningsbild
calmar
Inlägg: 540
Blev medlem: 23 november 2005, 13:14:41
Ort: Göteborg
Kontakt:

Re: Fråga om >> i C

Inlägg 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.
Användarvisningsbild
Micke_s
EF Sponsor
Inlägg: 6741
Blev medlem: 15 december 2005, 21:31:34
Ort: Malmö

Re: Fråga om >> i C

Inlägg 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)
Stalker
Inlägg: 9
Blev medlem: 19 april 2011, 18:16:53

Re: Fråga om >> i C

Inlägg 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
}
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Fråga om >> i C

Inlägg av sodjan »

Kompilaton (och eventuellt processorn) måste kunna skilja på
en "logic shift" och en "arithmetic shift".
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Fråga om >> i C

Inlägg 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.
Användarvisningsbild
adent
Inlägg: 4247
Blev medlem: 27 november 2008, 22:56:23
Ort: Utanför Jönköping
Kontakt:

Re: Fråga om >> i C

Inlägg 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.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Fråga om >> i C

Inlägg 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.
Stalker
Inlägg: 9
Blev medlem: 19 april 2011, 18:16:53

Re: Fråga om >> i C

Inlägg 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.
Skriv svar