Differences

This shows you the differences between two versions of the page.

Link to this comparison view

programare:laboratoare:lab11 [2025/12/14 02:11]
darius.neatu
programare:laboratoare:lab11 [2025/12/30 15:53] (current)
cosmin_stefan.popa [Noţiuni teoretice]
Line 1: Line 1:
 ===== PCLP Laborator11:​ Parametrii liniei de comandă. Preprocesorul. Funcții cu număr variabil de parametri. Opțiuni de compilare ​ ===== ===== PCLP Laborator11:​ Parametrii liniei de comandă. Preprocesorul. Funcții cu număr variabil de parametri. Opțiuni de compilare ​ =====
 +
 +**Resposabili:​**
 +  * [[ion_dorinel.filip@cti.pub.ro|Dorinel Filip (2016 - Prezent)]]
 +  * [[neatudarius@gmail.com|Darius Neațu (2016 - Prezent)]]
 +  * [[mihaela.vasile@gmail.com|Mihaela Vasile (2015)]]
  
 ==== Obiective ====  ==== Obiective ==== 
Line 19: Line 24:
 ==== Noţiuni teoretice ==== ==== Noţiuni teoretice ====
  
-==== Parametrii liniei de comandă ​====+=== Parametrii liniei de comandă ===
 Pentru a controla execuţia unui program, de multe ori este de dorit furnizarea datelor de lucru înaintea lansării în execuţie a programului,​ acesta urmând să se execute apoi fără intervenţia utilizatorului (aşa-numitul „batch mode”). Acest lucru se realizează prin intermediul parametrilor liniei de comandă. (Un exemplu cunoscut este lansarea compilatorului gcc în linia de comandă cu diverse argumente, care îi spun ce şi cum sa compileze.) Pentru a controla execuţia unui program, de multe ori este de dorit furnizarea datelor de lucru înaintea lansării în execuţie a programului,​ acesta urmând să se execute apoi fără intervenţia utilizatorului (aşa-numitul „batch mode”). Acest lucru se realizează prin intermediul parametrilor liniei de comandă. (Un exemplu cunoscut este lansarea compilatorului gcc în linia de comandă cu diverse argumente, care îi spun ce şi cum sa compileze.)
  
-Din punct de vedere al utilizatorului,​ parametrii liniei de comandă sunt simple argumente care se adaugă după numele unui program, în linia de comandă, la rularea sa. Elementele acestei liste de argumente sunt şiruri de caractere separate de spaţii. Argumentele care conţin spaţii pot fi combinate într-un singur argument prin inchiderea acestuia între ghilimele. Shell-ul este cel care se ocupă de parsarea liniei de comandă şi de crearea listei de argumente.+Din punctul ​de vedere al utilizatorului,​ parametrii liniei de comandă sunt simple argumente care se adaugă după numele unui program, în linia de comandă, la rularea sa. Elementele acestei liste de argumente sunt şiruri de caractere separate de spaţii. Argumentele care conţin spaţii pot fi combinate într-un singur argument prin inchiderea acestuia între ghilimele. Shell-ul este cel care se ocupă de parsarea liniei de comandă şi de crearea listei de argumente.
  
 Exemplu de apelare a unui program cu argumente în linia de comandă: Exemplu de apelare a unui program cu argumente în linia de comandă:
Line 38: Line 43:
   * myshell.c   * myshell.c
  
-Din punct de vedere al programatorului,​ parametrii liniei de comandă sunt accesibili prin utilizarea parametrilor funcţiei main(). Astfel, când se doreşte folosirea argumentelor liniei de comandă, funcţia main() se va defini astfel:+Din punctul ​de vedere al programatorului,​ parametrii liniei de comandă sunt accesibili prin utilizarea parametrilor funcţiei main(). Astfel, când se doreşte folosirea argumentelor liniei de comandă, funcţia main() se va defini astfel:
 <code c> <code c>
 int main(int argc, char *argv[]) int main(int argc, char *argv[])
Line 93: Line 98:
 </​code>​ </​code>​
 </​spoiler>​ </​spoiler>​
-==== Preprocesorul ​====+ 
 +=== Preprocesorul ===
  
 Preprocesorul este componenta din cadrul compilatorului C care realizează preprocesarea. În urma acestui pas, toate instrucţiunile de preprocesare sunt **înlocuite (substituite)**,​ pentru a genera cod C „pur”. Preprocesarea este o **prelucrare exclusiv textuală** a fişierului sursă. În acest pas nu se fac nici un fel de verificări sintactice sau semantice asupra codului sursă, ci doar sunt efectuate substituţiile din text. Astfel, preprocesorul va prelucra şi fişiere fără nici un sens în C. Preprocesorul este componenta din cadrul compilatorului C care realizează preprocesarea. În urma acestui pas, toate instrucţiunile de preprocesare sunt **înlocuite (substituite)**,​ pentru a genera cod C „pur”. Preprocesarea este o **prelucrare exclusiv textuală** a fişierului sursă. În acest pas nu se fac nici un fel de verificări sintactice sau semantice asupra codului sursă, ci doar sunt efectuate substituţiile din text. Astfel, preprocesorul va prelucra şi fişiere fără nici un sens în C.
Line 127: Line 133:
 Cele mai importante instrucţiuni de preprocesare sunt prezentate în continuare. Cele mai importante instrucţiuni de preprocesare sunt prezentate în continuare.
  
-=== Incluziune ​===+== Incluziune ==
  
 Probabil cea mai des folosită instrucţiune de preprocesare este cea de incluziune, de forma Probabil cea mai des folosită instrucţiune de preprocesare este cea de incluziune, de forma
Line 186: Line 192:
 </​code>​ </​code>​
 </​spoiler>​ </​spoiler>​
-=== Definirea de macro-uri ​===+== Definirea de macro-uri ==
  
 Instrucţiunile de preprocesare mai pot fi folosite şi pentru definirea de constante simbolice şi macroinstrucţiuni. De exemplu Instrucţiunile de preprocesare mai pot fi folosite şi pentru definirea de constante simbolice şi macroinstrucţiuni. De exemplu
Line 492: Line 498:
 </​note>​ </​note>​
  
-==== Instrucţiuni de compilare condiţionată ​====+=== Instrucţiuni de compilare condiţionată ===
  
 Instrucţiunile de compilare condiţionată sunt folosite pentru a „ascunde” fragmente de cod în funcţie de anumite condiţii. Formatul este următorul: Instrucţiunile de compilare condiţionată sunt folosite pentru a „ascunde” fragmente de cod în funcţie de anumite condiţii. Formatul este următorul:
Line 592: Line 598:
 </​spoiler>​ </​spoiler>​
  
-=== Includere multipla ​===+== Includere multipla ==
 Prevenirea includerii multiple a fişierelor antet se realizează astfel: Prevenirea includerii multiple a fişierelor antet se realizează astfel:
  
Line 771: Line 777:
 </​spoiler>​ </​spoiler>​
  
-=== Alte instrucţiuni ​===+== Alte instrucţiuni ==
  
 <code c> <code c>
Line 788: Line 794:
 Această instrucţiune de preprocesare modifică numărul liniei curente în valoarea specificată de **NUMBER**. În cazul în care este prezent şi parametru opţional **FILENAME** este modificat şi numele fişierului sursă curent. Astfel, mesajele de eroare şi avertismentele produse de compilator vor folosi numere de linie (şi eventual nume de fişiere) inexistente,​ „imaginare”,​ conform acestei instrucţiuni. Această instrucţiune de preprocesare modifică numărul liniei curente în valoarea specificată de **NUMBER**. În cazul în care este prezent şi parametru opţional **FILENAME** este modificat şi numele fişierului sursă curent. Astfel, mesajele de eroare şi avertismentele produse de compilator vor folosi numere de linie (şi eventual nume de fişiere) inexistente,​ „imaginare”,​ conform acestei instrucţiuni.
  
-==== Funcţii cu număr variabil de parametri ​====+=== Funcţii cu număr variabil de parametri ===
  
-=== Introducere ​===+== Introducere ==
 Marea majoritate a funcţiilor discutate până acum şi totalitatea funcţiilor realizate în cadrul laboratorului Marea majoritate a funcţiilor discutate până acum şi totalitatea funcţiilor realizate în cadrul laboratorului
 până în acest moment primeau ca parametrii un număr prestabilit de parametrii, de tipuri bine până în acest moment primeau ca parametrii un număr prestabilit de parametrii, de tipuri bine
Line 821: Line 827:
 </​note>​ </​note>​
  
-=== Implementarea funcţiilor cu număr variabil de parametri ​===+== Implementarea funcţiilor cu număr variabil de parametri ==
  
 Pentru prelucrarea listei de parametrii variabili este necesară includerea fişierului antet **stdarg.h**. Pentru prelucrarea listei de parametrii variabili este necesară includerea fişierului antet **stdarg.h**.
Line 1038: Line 1044:
 </​spoiler>​ </​spoiler>​
  
-==== Exerciții de laborator CB/CD ====+=== Opțiuni de compilare ​===
  
-Vă invităm să evaluați activitatea echipei de **programare CB/CD** și să precizați punctele tari și punctele slabe și sugestiile voastre de îmbunătățire a materiei. Feedback-ul vostru este foarte important pentru noi să creștem calitatea materiei în anii următori și să îmbunătățim materiile pe care le veți face în continuare.+== Compilatorul GCC ==
  
 +În cadrul laboratorului și pentru testarea temelor de casă se va folosi compilatorul GCC. GCC este unul dintre primele pachete software dezvoltate în cadrul Proiectului GNU (''​GNU'​s Not Unix''​) de către Free Software Foundation. Deși GCC se traducea iniţial prin ''​GNU C Compiler'',​ acesta a devenit între timp un compilator multifrontend,​ multi-backend,​ având suport pentru o serie largă de limbaje, ca C, C++, Objective-C,​ Ada, Java, etc, astfel că denumirea curentă a devenit ''​GNU Compiler Collection''​. În cadrul cursului de [[http://​ocw.cs.pub.ro/​programare|Programare]] ne vom referi totuşi numai la partea de C din suita de compilatoare.
 +
 +Compilatorul GCC rulează pe o gamă largă de echipamente hardware (procesoare din familia: ''​i386,​ alpha, vax, m68k, sparc, HPPA, arm, MIPS, PowerPC,''​ etc.) și de sisteme de operare (''​GNU/​Linux,​ DOS, Windows 9x/NT/2000, Solaris, Tru64, VMS, Ultrix, Aix ''​),​ fiind la ora actuală cel mai folosit compilator.
 +
 +Compilatorul GCC se apelează din linia de comandă, folosind diferite opțiuni, în funcție de rezultatul care se dorește (specificarea de căi suplimentare de căutare a bibliotecilor/​fișierelor antet, link-area unor biblioteci specifice, opțiuni de optimizare, controlul stagiilor de compilare, al avertisementelor,​ etc.). ​
 +
 +== Utilizare GCC ==
 +
 +<​hidden>​
 <​note>​ <​note>​
-Găsiți formularul ​de feedback în partea dreaptă a paginii principale de programare de pe cs.curs.pub.ro într-un frame numit “FEEDBACK” ([[http://cs.curs.pub.ro/2016/course/view.php?​id=17|moodle]]). Trebuie să fiți inrolați la cursul de programare, altfel veți primi o eroare de acces.+Instrucțiuni de instalare gcc - [[https://ocw.cs.pub.ro/courses/programare/vmchecker_conf#​instalare_gccmakeInstalare gcc/​make ​]]
 </​note>​ </​note>​
 +</​hidden>​
  
-Pentru a putea înțelege ​și valorifica feedback-ul mai ușor, apreciem orice formă ​de feedback negativ constructivă. Nu este suficient să ne spuneți, spre exemplu, //tema 5 a fost grea//, ne dorim să știm care au fost dificultățiile și, eventual, o propunere despre cum considerați că ar fi trebuit procedat.+Vom folosi pentru exemplificare un program simplu care tipărește la ieșirea standard un șir de caractere.
  
-Primul exercitiu presupune modificarea/​adaugarea de instructiuni unui cod existent pentru a realiza anumite lucruriIn momentul actual programul populeaza vectorul cu valorile parametrilor primiti de functie (atat timp cat valoarea parametrului este 0). Daca nu s-a populat tot vectorul, se adauga 0 pe pozitiile ramase goale.+<code c hello.c> 
 +#include <stdio.h>
  
-<spoiler ex1.c> +int main() { 
-<​code ​c ex1.c>+  printf("​Hello from your first program!\n"​);​ 
 +  return 0; 
 +} 
 +</code>
  
-#​include ​<stdio.h+Pentru compilarea programului se va lansa comanda (în linia de comandă):​ 
-#include <stdarg.h>+<code bash> gcc hello.c</code
 +presupunând că fișierul sursă se numește ''​hello.c''​.
  
-#define N 10+Pe un sistem de operare ''​Linux'',​ compilarea default va genera un executabil cu numele ''​a.out''​. Pentru rularea acestuia, trebuie executată comanda: 
 +<code bash> ./​a.out</​code>​
  
-void insert_elements(int *v, int n, ...) +Pentru un control mai fin al comportării compilatorului,​ sunt prezentate în tabelul următor cele mai folosite opţiuni ​(pentru lista completă studiaţi pagina de manual pentru GCC - ''​man gcc''​):
-+
-    int count = 0;+
  
-    va_list args; +^ Opțiune ^ Efect ^ 
-    ​va_start(argsn);+|**-o** nume_fișier|Numele fișierului de ieşire va fi nume_fişier. În cazul în care această opțiune nu este setată, se va folosi numele implicit ​(pentru fișiere executabile:​ a.out - pentru Linux).| 
 +|**-I** cale_către_fișiere_antet|Caută fișiere antet și în calea specificată.| 
 +|**-L** cale_către_biblioteci|Caută fișiere bibliotecă și în calea specificată.| 
 +|**-l** nume_bibliotecă|Link-editează biblioteca ''​nume_bibliotecă''​. **Atenție!!!** ''​nume_bibliotecă''​ nu este întotdeauna același cu numele fișierului antet prin care se include această bibliotecă. Spre exemplupentru includerea bibliotecii de funcții matematice, fișierul antet este math.h, iar biblioteca este ''​m''​.| 
 +|**-W** tip_warning|Afișează tipurile de avertismente specificate (Pentru mai multe detalii ''​man gcc''​ sau ''​gcc --help''​). Cel mai folosit tip este ''​all''​. Este indicat ca la compilarea cu ''​-Wall''​ să nu apară nici un fel de avertismente.| 
 +|**-c**|Compilează și asamblează,​ dar nu link-editează. Generează fișiere obiect, cu extensia ''​.o''​.| 
 +|**-S**|Se oprește după faza de compilare, fară să asambleze. Rezultă cod assembler în fișiere cu extensia ''​.s''​.|
  
-    int elem = va_arg(args,​ int); +<hidden> 
-    while (elem > 0 && count n) { +Despre etapele compilării puteți să citiți mai multe [[http://​elf.cs.pub.ro/​so/​wiki/​laboratoare/​laborator-01#​fazele-compilarii|aici]]. 
-        v[count++= elem; +</​hidden>​
-        elem = va_arg(args,​ int); +
-    }+
  
-    while (count < n) { +Exemplu =
-        v[count++] ​0; +
-    } +
-}+
  
-int main(void) +<code bash>gcc -o tema1 tema1.c -lm -Wall</​code>​
-{+
  
-    int v[N]; +Comanda de mai sus are ca efect compilarea șlink-editarea fişierului ''​tema1.c'',​ cu includerea bibliotecii matematice, afişând toate avertismentele. Fişierul de ieşire se va numi ''​tema1''​.
-    int i;+
  
-    insert_elements(vN, 1, 2, 3, 4, -1);+**Atenție!!!** Dacă folosiți opțiunea **-o**nu adăugați imediat după fișierele sursă. Acest lucru ar avea ca efect suprascrierea acestora și pierderea întregului conținut.
  
-    for (i 0; i < N; i ++) { +== Utilitarul Make ==
-      printf("​%d ", v[i]); +
-    }+
  
-    printf("​\n"​);​+<​note>​ 
 +Instrucțiuni de instalare gcc - [[https://​ocw.cs.pub.ro/​courses/​programare/​vmchecker_conf#​instalare_gccmake| Instalare gcc/make ]] 
 +</​note>​
  
-    return 0; +Utilitarul ''​make''​ determină automat care sunt părțile unui proiect care trebuie recompilate ca urmare a operării unor modificări și declanşează comenzile necesare pentru recompilarea lor. Pentru a putea utiliza ''​make'',​ este necesar un fișier de tip ''​makefile''​ (numit de obicei ''​Makefile''​ sau ''​makefile''​) care descrie relațiile de dependenţă între diferitele fișiere din care se compune programul şi care specifică regulile de actualizare pentru fiecare fişier în parte. 
-}+ 
 +În mod normal, într-un program, fişierul executabil este actualizat (recompilat) pe baza fișierelor-obiect,​ care la rândul lor sunt obținute prin compilarea fișierelor sursă. Totuși, acest utilitar poate fi folosit pentru orice proiect care conţine dependenţe şi cu orice compilator/​utilitar care poate rula în linia de comandă. Odată creat fișierul ''​makefile'',​ de fiecare dată când apare vreo modificare în fișierele sursă, este suficient să rulăm utilitarul ''​make''​ pentru ca toate recompilările necesare să fie efectuate. Programul ''​make''​ utilizează fișierul Makefile ca bază de date şi pe baza timpilor ultimei modificări a fișierelor din Makefile decide care sunt fișierele care trebuie actualizate. Pentru fiecare din aceste fișiere, sunt executate comenzile precizate in Makefile. În continuare prezentăm un exemplu simplu. 
 + 
 +<code bash> 
 +# Declaratiile de variabile 
 +CC = gcc 
 +CFLAGS = -Wall -lm 
 +SRC = radical.c 
 +EXE = radical 
 + 
 +# Regula de compilare 
 +all: 
 + $(CC) -o $(EXE) $(SRC) $(CFLAGS) 
 + 
 +# Regulile de "​curatenie"​ (se folosesc pentru stergerea fisierelor intermediare si/sau rezultate) 
 +.PHONY : clean 
 +clean : 
 + rm -f $(EXE) *~
 </​code>​ </​code>​
-</​spoiler>​ 
-Cerinte: 
-   * Sa se modifice functia astfel incat sa se poata popula si un vector cu elemente de tip char. Functia va fi declarata astfel: ​ 
-     * **void insert_elemenets(void *v, int n, char type, …)** - unde type va specifica tipul (‘d’ pentru int si ‘c’ pentru char). 
-     * Daca nu se umple tot vectorul cu valori, vor trebui puse niste valori default (cum este si in codul deja existent): pentru int va ramane valoarea 0, iar pentru char va fi ‘a’. 
-   * In functie de simbolul NUMBERS, programul va popula fie un vector de numere, fie un vector de caractere si il va afisa (se pot lasa valori specifice trimise la functia de populare) 
-     * Simbolul nu trebuie definit in cadrul fisierului sursa 
  
-**Următoarele două probleme vă vor fi date de asistent în cadrul laboratorului.** +**Atenție!!!** Este obligatorie folosirea tab-urilor (nu spații!). 
-<​hidden>​ +Mai multe informații puteți găsiti pe [[http://www.gnu.org/software/make|pagina proiectului]]. 
-Link direct către lista completă de probleme: ​[[https://docs.google.com/document/d/​1cOh9mCbPhAT6DqRUGUbRPBmaV01yK4-ESJdYkqZuDws/​edit|aici]] +
-</​hidden>​+
  
 ==== Exerciții ==== ==== Exerciții ====
Line 1111: Line 1139:
  
 ==== Referinţe ==== ==== Referinţe ====
-  * TODO+  * https://​en.cppreference.com/​w/​c/​variadic.html 
 +  * https://​en.cppreference.com/​w/​c/​preprocessor.html
programare/laboratoare/lab11.1765671073.txt.gz · Last modified: 2025/12/14 02:11 by darius.neatu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0