Zavarban vagyok a register
kulcsszó C-ben történő használatával kapcsolatban. Általában azt mondják, hogy a használata nem ” Szüksége van , mint ebben a kérdésben a stackoverflow -ra.
Ez a kulcsszó teljesen felesleges a C-ben a modern fordítók miatt, vagy vannak olyan helyzetek, amikor még mindig hasznos lehet? Ha igen, melyek azok a helyzetek, amikor a register
kulcsszó használata valóban hasznos?
Megjegyzések
- Úgy gondolom, hogy az összekapcsolt kérdés és a rá adott válaszok megegyeznek az itt elvártakkal. Tehát nem lesznek új információk, amelyeket itt megszerezhet.
- @UwePlonus ugyanaz a
const
kulcsszóval kapcsolatban, de ez a kérdés bebizonyította, hogy tévedtem. Tehát ‘ Várok, és megnézem, mit kapok. - Úgy gondolom, hogy a
const
kulcsszó valami más, mint a regisztráció. - Ez ‘ s hasznos, ha véletlenül visszalép az időben, és kénytelen használni az egyik korai C fordítót. Ezen kívül ‘ egyáltalán nem hasznos, ‘ évek óta teljesen elavult.
- @ UwePlonus Csak arra gondoltam, hogy lehetnek olyan ismeretlen forgatókönyvek, amelyekben egy kulcsszó hasznos lehet.
Válasz
Ez a nyelv szempontjából nem felesleges, csupán annyi, hogy használatával azt mondja a fordítónak, hogy “inkább” egy változót tárolna a nyilvántartásban. Mindazonáltal teljesen nulla garancia arra, hogy ez valóban futás közben történnek.
Megjegyzések
- Ezen felül ‘ szinte mindig így van a fordító tudja a legjobban, és te ‘ pazarolod a lélegzetedet
- @jozefg: még rosszabb. Fennáll annak a kockázata, hogy a fordító eleget tesz kérésednek / tippednek, és produkál ennek következtében rosszabb kód.
Válasz
Mint már említettük, a fordító optimalizálói lényegében ren derítse el az register
kulcsszót az álnév megakadályozásától eltérő célokra. Vannak azonban teljes kódbázisok, amelyeket optimalizálás kikapcsolásával állítanak össze (-O0
a gcc-speak ben). Ilyen kód esetén a register
kulcsszó nagy hatással lehet. Pontosabban, azok a változók, amelyek egyébként rést kapnának a veremben (azaz az összes függvényparaméter és az automatikus változó) elhelyezhető közvetlenül egy regiszterbe, ha a register
kulcsszó.
Itt van egy valós példa: tegyük fel, hogy valamilyen adatbázis-visszakeresés történt, és hogy a visszakeresési kód a letöltött duplát egy C struktúrába töltötte. Tegyük fel továbbá, hogy ennek a C struktúrának néhány részhalmaza át kell másolni egy másik struktúrába – lehet, hogy ez a második struktúra egy gyorsítótár-rekord, amely az adatbázisban tárolt metaadatokat reprezentálja, amely a memória korlátai miatt az egyes metaadat-rekordok egy részhalmazát tárolja csak az adatbázisban tárolva.
Adott egy olyan függvény, amely mutatót visz minden struktúra típushoz, és amelynek egyetlen feladata néhány tag másolása az eredeti struktúrából a második struktúrába: a struktúra mutató változók a veremben fognak élni. Mivel a hozzárendelések egy struktúra tagjától származnak a többi címre a struktúra címei minden hozzárendelésnél be kell tölteni egy regiszterbe a másolni kívánt struktúra tagok hozzáférésének végrehajtása érdekében. Ha a strukturális mutatókat a register
kulcsszóval deklarálnánk, akkor a struktúrák címei a regiszterekben maradnának, hatékonyan kivágva az egyes hozzárendelésekhez a load-address-to-register utasításokat.
Ismét ne feledje, hogy a fenti leírás az nem optimalizált kódra vonatkozik.
Válasz
Alapvetően azt mondod a fordítónak, hogy nem fogod megadni a változó címét, és a fordító ezután látszólag elkészítheti további optimalizálás. Ha jól tudom, a modern fordítók eléggé képesek meghatározni, hogy egy változó nyilvántartható-e / szabad-e nyilvántartásban vagy sem.
Példa:
int main(){ int* ptr; int a; register int b; ptr = &a; ptr = &b; //this won"t compile return 0; }
Megjegyzések
- Hajtsa le a következőket, vagy vegye fel a címét?
- @detly: természetesen igazad van
Válasz
A 16 bites számítógépes napokban gyakran több regiszterre volt szükség a 32 bites szorzások és osztások végrehajtásához. lebegőpontos egységeket integráltak chipekbe, majd a 64 bites architektúrák “átvették”, mind a regiszterek szélessége, mind azok száma kiszélesedett. Ez végül a CPU teljes újratervezéséhez vezet. Lásd: Fájlok regisztrálása a Wikipédián.
Röviden, egy kis időbe telik a figu derítse ki, mi is történik valójában, ha 64 bites X86 vagy ARM chipet használ.Ha 16 bites beágyazott CPU-t használ, akkor ez valójában hozhat valamit. Azonban a legtöbb kicsi beágyazott chip nem futtat kritikus időt – a mikrohullámú sütő másodpercenként 10 000-szer vesz mintát az érintőpadról – semmi sem erőlteti 4Mhz CPU.
Megjegyzések
- 4 MIPS / 10 000 közvélemény-kutatás / sec = 400 utasítás / közvélemény-kutatás. Ez ‘ közel sem akkora margó, mint amennyit ‘ szeretne. Vegye figyelembe azt is, hogy jó néhány 4 MHz-es processzort mikrokódoltak belülről, ami azt jelentette, hogy közel sem voltak 1 MIP / MHz-hez.
- @ JohnR.Strohm – Előfordulhatnak olyan helyzetek, amikor igazolni lehet, hogy pontosan hány utasítást kell kitalálni. megtervezi ‘ t, de gyakran az olcsóbb kiút az, ha csak egy gyorsabb chipet kapunk, és a terméket kinyitjuk az ajtón. A megadott példában természetesen nem kell ‘ folytatni a mintavételt 10 000-nél, ha van parancsa – lehet, hogy nem folytatja a mintavételt negyed másodpercig, nem árt Kész. Egyre nehezebb kitalálni, hogy a programozó által irányított optimalizálás hol számít majd.
- Nem mindig lehet ” csak gyorsabb chipet szerezni, és megkapni a termék az ajtón “. Fontolja meg a valós idejű képfeldolgozást. 640×480 képpont / képkocka x 60 képkocka / másodperc x N képpontonkénti utasítás gyorsan hozzáadódik. (A valós idejű képfeldolgozás tanulsága, hogy vért izzad a pixelmagjai fölött, és szinte mindent figyelmen kívül hagy, mivel soronként egyszer, foltonként vagy képkockánként egyszer fut, szemben soronként több százszor, ill. javítás vagy képkockánként tíz- vagy százezerszer.)
- @ JohnR.Strohm – a valós idejű képfeldolgozási példát véve feltételezném, hogy a minimális környezet 32 bit. Végtaggal kimenni (mert nem tudom, mennyire praktikus ez) sok chipbe épített grafikus gyorsító is használható lehet képfelismerésre, így ARM chipek (például ), amelyek integrált renderelő motorokkal rendelkeznek, további ALU-kkal rendelkezhetnek, amelyek felhasználhatók felismerésre. Addigra a ‘ regiszter ‘ kulcsszó optimalizálására való felhasználása a probléma apró része.
Válasz
Annak megállapítása érdekében, hogy a regiszter kulcsszónak van-e jelentősége, apró példakódok nem fognak megadni. Itt van egy c-kód ami számomra azt sugallja, hogy a register kulcsszónak még mindig van jelentősége. De ez más lehet a Linuxos GCC-nél, nem tudom. LESZ-e az int k & l regisztráció egy CPU regiszterben vagy sem? A Linux-felhasználóknak (különösen) fordítaniuk kell a GCC-vel és az optimalizálással. A Borland bcc32 használatával a regiszter kulcsszó működni látszik (ebben a példában), mivel a & -operator hibakódokat ad meg a regiszter által deklarált egész számokhoz. JEGYZET! NEM ez a helyzet egy apró példával a Borland Windows rendszeren! Annak érdekében, hogy valóban lássuk, mit optimalizál a fordító vagy sem, annak többnek kell lennie, mint egy apró példának. Az üres ciklusok nem fognak megtörténni! Ennek ellenére – HA egy cím elolvasható a & -operátorral, akkor a változó nem lesz tárolva egy CPU regiszterben. De ha egy nyilvántartott deklarált változót nem lehet elolvasni (hibakódot okozva a fordításnál) – azt kell feltételeznem, hogy a regiszter kulcsszó valóban a CPU regiszterbe helyezi a változót. Különböző platformokon eltérhet, nem tudom . (Ha működik, akkor a “kullancsok” száma jóval alacsonyabb lesz a regisztráció deklarációjával együtt.
/* reg_or_not.c */ #include <stdio.h> #include <time.h> #include <stdlib> //not requiered for Linux #define LAPSb 50 #define LAPS 50000 #define MAXb 50 #define MAX 50000 int main (void) { /* 20 ints and 2 register ints */ register int k,l; int a,aa,b,bb,c,cc,d,dd,e,ee,f,ff,g,gg,h,hh,i,ii,j,jj; /* measure some ticks also */ clock_t start_1,start_2; clock_t finish_1,finish_2; long tmp; //just for the workload /* pointer declarations of all ints */ int *ap, *aap, *bp, *bbp, *cp, *ccp, *dp, *ddp, *ep, *eep; int *fp, *ffp, *gp, *ggp, *hp, *hhp, *ip, *iip, *jp, *jjp; int *kp,*lp; /* end of declarations */ /* read memory addresses, if possible - which can"t be done in a CPU-register */ ap=&a; aap=&aa; bp=&b; bbp=&bb; cp=&c; ccp=&cc; dp=&d; ddp=ⅆ ep=&e; eep=ⅇ fp=&f; ffp=&ff; gp=&g; ggp=≫ hp=&h; hhp=&hh; ip=&i; iip=ⅈ jp=&j; jjp=&jj; //kp=&k; //won"t compile if k is stored in a CPU register //lp=&l; //same - but try both ways ! /* what address , isn"t the issue in this case - but if stored in memory some "crazy" number will be shown, whilst CPU-registers can"t be read */ printf("Address a aa: %u %u\n",a,aa); printf("Address b bb: %u %u\n",b,bb); printf("Address c cc: %u %u\n",c,cc); printf("Address d dd: %u %u\n",d,dd); printf("Address e ee: %u %u\n",e,ee); printf("Address f ff: %u %u\n",f,ff); printf("Address g gg: %u %u\n",g,gg); printf("Address h hh: %u %u\n",h,hh); printf("Address i ii: %u %u\n",i,ii); printf("Address j jj: %u %u\n\n",j,jj); //printf("Address k: %u \n",k); //no reason to try "k" actually is in a CPU-register //printf("Address l: %u \n",l); start_2=clock(); //just for fun /* to ensure workload */ for (a=1;a<LAPSb;a++) {for (aa=0;aa<MAXb;aa++);{tmp+=aa/a;}} for (b=1;b<LAPSb;b++) {for (bb=0;bb<MAXb;bb++);{tmp+=aa/a;}} for (a=1;c<LAPSb;c++) {for (cc=0;cc<MAXb;cc++);{tmp+=bb/b;}} for (d=1;d<LAPSb;d++) {for (dd=0;dd<MAXb;dd++);{tmp+=cc/c;}} for (e=1;e<LAPSb;e++) {for (ee=0;ee<MAXb;ee++);{tmp+=dd/d;}} for (f=1;f<LAPSb;f++) {for (ff=0;ff<MAXb;ff++);{tmp+=ee/e;}} for (g=1;g<LAPSb;g++) {for (gg=0;gg<MAXb;gg++);{tmp+=ff/f;}} for (h=1;h<LAPSb;h++) {for (hh=0;hh<MAXb;hh++);{tmp+=hh/h;}} for (jj=1;jj<LAPSb;jj++) {for (ii=0;ii<MAXb;ii++);{tmp+=ii/jj;}} start_1=clock(); //see following printf for (i=0;i<LAPS;i++) {for (j=0;j<MAX;j++);{tmp+=j/i;}} /* same double loop - in supposed memory */ finish_1=clock(); //see following printf printf ("Memory: %ld ticks\n\n", finish_1 - start_1); //ticks for memory start_1=clock(); //see following printf for (k=0;k<LAPS;k++) {for (l=0;l<MAX;l++);{tmp+=l/k;}} /* same double loop - in supposed register*/ finish_1=clock(); //see following printf printf ("Register: %ld ticks\n\n", finish_1 - start_1); //ticks for CPU register (?) any difference ? finish_2=clock(); printf ("Total: %ld ticks\n\n", finish_2 - start_2); //really for fun only system("PAUSE"); //only requiered for Windows, so the CMD-window doesn"t vanish return 0; }
Megjegyzések
- Nulla fölötti osztás lesz, kérjük, változtassa meg a {tmp + = ii / jj;} értéket {tmp + = jj / ii;} -re – nagyon sajnálom ezt
- Hagyja k és i-t is 1-től kezdődik – nem nulla. Nagyon sajnálom.
- A válaszokat szerkesztheti, ahelyett, hogy javításokat írna a megjegyzésekbe.