C-ben bool helyett altalaban int-et hasznalnak. Minden nemnulla ertek igazat jelent es csak a nulla hamis.
Elönyösebb a maszkot eltolni, igy a fordito optimalis kodot tud generalni, amelyben egyaltalan nem lesz eltolas:
if ( input & (1<<5)) { ... }
A blokkot akkor hajtja vegre, ha az input valtozo 5-ik bitje 1.
Szerintem abbol lehet kiindulni, hogy optimalizalt modban a fordito a assembler hasonlo minösegü kodot fog generalni. Szerintem assemblert gyakorlatilag csak extrem kiveteles körülmenyek között erdemes hasznalni. Ha leakarod ellenörizni a generalt kodot, akkor a "-S" kapcsoloval kell forditani. Az assembler file neve ".s"-re fog vegzödni.
Peldaul a kovetkezo fuggveny 1-et ad vissza, ha az input parameter 5-ik bitje 1, egyebkent 0-at.
unsigned f(unsigned input) { return input & (1<<5) ? 1 : 0; }
A gcc a kovetketo kodot generalja:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
shrl $5, %eax
andl $1, %eax
popl %ebp
ret
Ami egy meglepöen intelligens valasz, hiszen a felteteles ugrast önmagatol atalakitotta egy eltolasse es egy es-operaciova. Ez altalaban gyorsabb, mert a modern architekturakban minden feltetes ugras jelentösen lassithatja a programfutast, mert a processzor a pipeline miatt jump-prediction-t hasznal, ami ha nem jön be alapvetöen lassabb mint jopar müvelet vegrehajtasa.
A fenti megoldas persze csak ebben a specialis esetben lehetseges, amennyiben pl. lebegöpontos szamot adnank vissza, itt a fenti trükk nem müködik:
double f(unsigned input) { return input & (1<<5) ? 1.0 : 0.0; }
( -O3 agressziv optimalizalassal forditva a következö kodot adja:)
pushl %ebp
movl %esp, %ebp
testb $32, 8(%ebp)
je .L2
fld1
.L3:
popl %ebp
ret
.p2align 4,,7
.L2:
fldz
jmp .L3
Itt lathatjuk, hogy most megörizte a 32-vel törtenö maszkolast (tehat az 1<<5 müveletet forditasi idöben elvegezte), valamint kihasznalta a tehat megint eleg jo kodot generalt.
Utoljara nezzük meg, hogy mi törtenik, ha az a következö evvel ekvivalens, de kisse szuboptimalisabb kodot forditjuk (elöször az inputot balra toljuk aztan maszkolunk):
double f(unsigned input) { return ((input >> 5) & 1)? 1.0 : 0.0; }
Eredmeny:
pushl %ebp
movl %esp, %ebp
testb $32, 8(%ebp)
je .L2
fld1
.L3:
popl %ebp
ret
.p2align 4,,7
.L2:
fldz
jmp .L3
Azaz ugyanaz mint az elöbb, megint nem törtenik eltolas futasidöben!
A tanulsag: nem erdemes tul sokat agyalni alacsony szintü trükkökön, a fordito jo esellyel megtalalja az optimalis megoldast, talan jobbat meg jobbat is, mint ami a programozonak eszebe jutna. Erdemes inkabb a magasabb szintü algoritmikus kerdesekre koncentralni assembler tuningolas helyett.