A compilator este un program asta se traduce prin citire umană cod sursa în codul mașinii executabil de computer. Pentru a face acest lucru cu succes, codul care poate fi citit de om trebuie să respecte prevederile sintaxă regulile limbajului de programare în care este scris. Compilatorul este doar un program și nu vă poate repara codul pentru dvs. Dacă faceți o greșeală, trebuie să corectați sintaxa sau aceasta nu va compila.
Ce se întâmplă când compilați codul?
Complexitatea unui compilator depinde de sintaxa limbajului și de câtă abstractizare acel limbaj de programare prevede. Un compilator C este mult mai simplu decât un compilator pentru C ++ sau C #.
Analiză lexicală
Când compilați, compilatorul citește mai întâi un flux de caractere dintr-un fișier cu cod sursă și generează un flux de jetoane lexicale. De exemplu, codul C ++:
int C = (A * B) +10;
ar putea fi analizate ca aceste jetoane:
- tastați „int”
- variabila "C"
- equals
- leftbracket
- variabila "A"
- ori
- variabila "B"
- rightbracket
- la care se adauga
- literal "10"
Analiza sintactică
Ieșirea lexicală merge către partea analizatorului sintactic al compilatorului, care folosește regulile gramaticii pentru a decide dacă intrarea este valabilă sau nu. Dacă nu variabile A și B au fost declarate anterior și au fost de aplicare, compilatorul ar putea spune:
- „A”: identificator nedeclarat.
Dacă au fost declarați, dar nu inițializați. compilatorul emite un avertisment:
- variabila locală „A” folosită fără a fi inițializată.
Nu ar trebui să ignorați niciodată avertismentele compilatorului. Vă pot sparge codul în mod ciudat și neașteptat. Remediați întotdeauna avertismentele compilatorului.
O trecere sau două?
Unele limbaje de programare sunt scrise astfel încât un compilator poate citi codul sursă o singură dată și să genereze codul mașinii. Pascal este un astfel de limbaj. Mulți compilatoare necesită cel puțin două treceri. Uneori, este din cauza declarațiilor înainte funcții sau clase.
În C ++, o clasă poate fi declarată, dar nu este definită până mai târziu. Compilatorul nu este capabil să calculeze câtă memorie are nevoie de clasă până când compilează corpul clasei. Trebuie să recitească codul sursă înainte de a genera codul corect al mașinii.
Generarea codului mașinii
Presupunând că compilatorul finalizează cu succes analizele lexicale și sintactice, etapa finală este generarea codului mașinii. Acesta este un proces complicat, în special cu procesoare moderne.
Viteza compilatului executabil codul trebuie să fie cât mai rapid și poate varia enorm în funcție de calitatea codului generat și de cât de mult a fost solicitată.
Majoritatea compilatoarelor vă permit să specificați cantitatea de optimizare - cunoscută în mod obișnuit pentru compilări rapide de depanare și optimizare completă pentru codul lansat.
Generarea codului este provocatoare
Scriitorul compilatorului se confruntă cu provocări atunci când scrie un generator de cod. Multe procesoare accelerează procesarea folosind
- Instrucțiuni de conducte
- Intern memorii cache.
Dacă toate instrucțiunile dintr-un cod buclă poate fi ținut în Procesor cache, atunci acea buclă rulează mult mai repede decât atunci când CPU trebuie să preia instrucțiuni din memoria RAM principală. Cache-ul CPU este un bloc de memorie încorporat în cipul CPU la care este accesat mult mai rapid decât datele din memoria RAM principală.
Cache și cozi
Majoritatea procesoarelor au o coadă pre-preluare în care CPU citește instrucțiuni în cache înainte de a le executa. Dacă se întâmplă o ramură condiționată, procesorul trebuie să reîncarce coada. Codul ar trebui generat pentru a minimiza acest lucru.
Multe CPU au părți separate pentru:
- Aritmetică întreagă (numere întregi)
- Aritmetica cu punct flotant (numere fracționale)
Aceste operații pot fi adesea rulate în paralel pentru a crește viteza.
Compilatoarele generează de obicei codul mașinii în fișierele obiect care sunt apoi legat împreună de un program linker.