Sunteți pe pagina 1din 35

Limbajul C: Funcții, clase de memorare, tipuri de date

structurate, directive de preprocesare

Grigore Albeanu
g.albeanu.mi@spiruharet.ro

Versiunea 2018 G. Albeanu, Fundamentele programării - 1


Limbajul C - part 2
Funcții C
◼ Structura proiectelor
C complexe
◼ Functia main()
◼ Functii C

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 2


C - part 2
Prototipul unei funcții C/C++
◼ Funcţiile sunt întotdeauna definite la nivelul (cel mai)
exterior al programului şi au asociate adrese fixe de
memorie. Sunt implicit în clasa extern, deci sunt
vizibile în modulul în care sunt definite, de la locul de
definire spre sfârşitul fişierului, ca şi în toate celelalte
module de program.
◼ Pentru a limita vizibilitatea numai la modulul în care
sunt definite se utilizează cuvântul cheie static (clasa
static extern !!!).
◼ De obicei, la începutul fişierului se pune prototipul
funcţiei:
Tip_rezultat id_functie(tip1, tip2, …, tipn);

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 3


C - part 2
Declarații/Definiții
◼ O declaraţie C specifică atributele unui identificator sau mulţime de
identificatori.
◼ Regulile sintactice care stau la baza scrierii declarațiilor sunt redate prin:

<declaraţie> ::= <specificator declaraţie> <listă declaratori de iniţializare>;


<specificator declaraţie> ::=
<clasa de memorare> <specificator declaraţie> |
<specificator tip> <specificator declaraţie> |
<calificator tip> <specificator declaraţie>
<listă declaratori de iniţializate> ::= <declarator iniţializare> |
<listă declaratori iniţializare>, <declarator iniţializare>
<declarator iniţializare> ::= <declarator> | <declarator> = <iniţializare>

◼ A face o declaraţie nu presupune şi alocarea memoriei pentru indentificatorul


declarat. Există situaţii când alocarea se realizează în altă unitate de
translatare (cazul datelor externe).
◼ Tipuri de variabile: locale, globale. Variabile locale (se declară la începutul
funcţiilor, în blocul funcţiei sau blocuri ale instrucţiunilor! ) Variabile globale (se
declară în exteriorul tuturor funcţiilor)
◼ Se precizează: clasa de alocare, tipul, numele şi o eventuală iniţializare.
Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 4
C - part 2
Atributele datelor
◼ Declaraţia unui identificator asociază numelui în mod explicit
sau implicit o serie de atribute din mulţimea următoare:
Clasa de memorare - localizează zona de memorie în care este plasat
elementul declarat (zona de date, un registru al procesorului, stiva
mediului de programare, zona de alocare dinamică) şi delimitează durata
alocării (întreg timpul de executare a programului, executarea unei funcţii
sau a unui bloc etc.)
Domeniul numelui - reprezintă porţiunea din program în care poate fi utilizat
identificatorul pentru accesarea informaţiei asociate şi este determinat de
poziţia declaraţiei.
Durata de stocare - reprezintă perioada cât elementul asociat există efectiv
în memorie.
Legătura - indică modul de asociere a unui identificator cu un anumit obiect
sau funcţie, în procesul de editare a legăturilor (rezolvare a referinţelor
externe).
Tipul datei (standard sau definit de utilizator) - descrie informaţia conţinută
de elementul definit de identificator.

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 5


C - part 2
Clasa de alocare/memorare
◼ determină unde se va rezerva spațiu pentru variabilă
◼ determină durata de viață, vizibilitatea și modalitatea de
inițializare.
◼ clase de alocare: auto(matic), register, static (intern) și
static extern
◼ Variabilele din clasa automatic sunt definite în interiorul
funcţiilor, fiind locale funcției în care au fost definite (nu
pot fi accesate din alte funcții).
◼ Durata de viață a variabilelor din clasa automatic este
durata de executare a functiei respective, aceste variabile
<dispărând> la încheierea executării funcției.
◼ !!! Variabilelor auto li se alocă spatiu folosind stiva
programului, la intrarea în funcție, iar la ieșirea din funcție
stiva este descărcată.
Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 6
C - part 2
Clasa auto
◼ Clasa auto este implicită: dacă nu este specificată nici o
clasă de alocare, declaraţiile din interiorul unei funcţii
creează variabile în clasa automatic, deci în mod implicit,
toate variabilele sunt memorate în memoria volatilă
gestionată ca o stivă.
◼ Parametrii funcţiilor sunt transmişi, de asemenea, prin
stivă (de la dreapta la stânga!).
◼ Clasa automatic se poate specifica prin cuvântul cheie
auto.
◼ Exemplu: int f(int *x, int *y){ auto int t; t=*x; *x=*y; *y=t;}

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 7


C - part 2
Clasa register
◼ Variabilele definite în interiorul unei funcţii, cu clasa de alocare
register sunt asemănătoare celor din clasa auto, cu excepţia
faptului că, dacă e posibil!, ele vor fi memorate în registrele UC
(procesorului) şi nu în memoria volatilă (RAM – Random Access
Memory).
◼ * Nu există adresă de memorie asociată.
◼ Numai un număr limitat de variabile pot fi ţinute în registre. Când
nu mai sunt registre disponibile, compilatorul le trece în clasa
auto, dar cu păstrarea restricţiei *
◼ Variabilele parametri formali pot fi declarate în clasa register, de
exemplu: void f(register int x); aceasta neafectând modul lor
de transmitere către funcţie (se face tot prin stivă), ci numai
faptul ca vor fi ţinute în registrele maşinii pe durata executării
funcţiei.
◼ Variabilele din clasele auto şi register nu îşi păstrează valoarea
de la un apel la altul al funcţiei în care sunt definite. Dacă sunt
iniţializate, iniţializarea are loc la fiecare nouă intrare în funcţie.
Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 8
C - part 2
Clasa static intern
◼ Variabilele din clasa static intern sunt memorate în
locaţii fixe de memorie (au permanent asociată
aceeaşi adresă).
◼ Durata de viaţă a datelor statice - pe parcursul
executării întregului program.
◼ O variabilă din clasa static, definită în interiorul unei
funcţii (este în clasa static intern), este specificată
prin cuvântul cheie static. Dacă static nu apare, se
consideră clasa auto.
◼ O variabilă din clasa static intern (obligatoriu trebuie
inițializată) se iniţializează numai la primul apel (prin
codul generat!)

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 9


C - part 2
Cuvântul cheie extern
◼ Pentru a accesa o variabilă definită la nivel exterior în
alt modul (fişier) decât cel curent, se declară variabila
explicit folosind cuvântul cheie extern.
◼ Pentru a accesa funcţii definite în alt modul (de
exemplu funcţii de bibliotecă !) este suficientă
prezenţa prototipului în modulul în care este folosită
funcţia, dar se poate declara şi explicit folosind
cuvintul cheie extern.
◼ O variabilă (chiar şi o funcţie) poate fi declarată în
mai multe module (cu extern), dar trebuie definită
într-un singur modul.

◼ Definiție --------------- Declarație !!!!!!!!

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 10


C - part 2
Aplicații multi-fișier în C/C++

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 11


C - part 2
Concluzii – domenii de vizibilitate
◼ În C declaraţia unei variabile trebuie să preceadă orice referire a ei. Ea poate
apărea în exteriorul oricărei funcţii, în lista de parametri formali a unei funcţii sau
la începutul unui bloc. Domeniul numelui este regiunea dintr-un program C în
care identificatorul este “vizibil”. Poziţia declaraţiei determină următoarele
domenii:
Domeniul bloc - caracterizează identificatorii locali (identificatorii declaraţi în
interiorul unui bloc au domeniul cuprins între declaraţie şi sfârşitul blocului;
parametrii formali din definiţia unei funcţii au ca domeniu blocul funcţiei).
Domeniul fişier - caracterizează identificatorii declaraţi în exteriorul oricărei
funcţii - numiţi identificatori globali - şi care au domeniul cuprins între
declaraţie şi sfârşitul fişierului.
Domeniul funcţie - aplicabil pentru etichetele instrucţiunilor şi este blocul
funcţiei.
Domeniul prototip - definit pentru identificatorii specificaţi în lista de parametrii
din prototipul unei funcţii - şi care au domeniul limitat la acel prototip.
◼ Partea din domeniu în care informaţia asociată este accesibilă se numeşte zonă
de vizibilitate. O declaraţie a unui identificator este vizibilă în tot domeniul său
mai puţin blocurile sau funcţiile în care identificatorul este redeclarat. Pentru
identificatorii globali se poate repeta declaraţia, dar iniţializarea trebuie să se
facă o singură dată.

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 12


C - part 2
Concluzii – durata de stocare
Din punct de vedere al duratei de stocare, sunt posibile trei situaţii:

◼ Durată statică: Obiectele cu durată statică au alocată zona de


memorie pe toată durata de executare a programului. Toate variabilele
globale au durată statică. Alte variabile pot avea această calitate prin
utilizarea specificatorilor static sau extern.

◼ Durată locală: Obiectele cu durată locală sunt cele automatice -


spaţiul de memorare se alocă (în stivă sau în registru) la intrarea în
executare a blocului sau funcţiei şi este eliberat la ieşirea din bloc sau
din funcţie. În concluzie, orice obiect automatic dispare la încheierea
duratei sale de viaţă, deci informaţia conţinută de acesta “se pierde”.

◼ Durată dinamică: Pentru obiectele cu durată dinamică, zona de


memorie este alocată şi eliberată la iniţiativa programatorului prin
apelarea unor funcţii C (de exemplu: malloc, free).

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 13


C - part 2
Tipuri de date structurate
struct - este cuvânt cheie pentru construirea
unui tip înregistrare;
<id_tip> - este un identificator ce desemnează
numele tipului structuri care este declarată;
<tip_câmp_i> - tipul câmpului i;
<id_câmp_i> - identificatorul câmpului i
(câmpurile se mai numesc şi membrii);
<listă identificatori de tip struct> - lista
identificatorilor declaraţi.
Dacă numele tipului <id_tip> lipseşte, structura se numeşte anonimă. Dacă lista identificatorilor
declaraţi lipseşte, s-a definit doar tipul structură. Cel puţin una dintre aceste specificaţii trebuie să
existe.
Dacă <id_tip> este prezent, ulterior, se pot declara noi variabile de tip structură prin intermediul
declaraţiei: struct <id_tip> <lista noilor identificatori>;
Referirea unui membru al unei variabile de tip structură se face folosind operatorul de selecţie (.)
într-o expresie care precizează identificatorul variabilei şi al câmpului.
Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 14
C - part 2
struct – exemple (1)
#include <stdio.h>
struct student {
int id;
char *nume;
struct tnode { /* the node: */
float p;
char *word; /* points to the text */
} s1, s2, s3; int count; /* number of occurrences */
int main(void) { struct tnode *left; /* left link */
struct student st; struct tnode *right; /* right link */
s1.id=1; s2.nume = “Ada"; };
s3.p = 90.5;
printf(" Nr matricol: %d \n", s1.id);
printf(" Numele: %s \n", s2.nume);
printf(" Media: %f \n", s3.p);
return 0;
} http://cslibrary.stanford.edu/110/BinaryTrees.html
Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 15
C - part 2
struct – exemple (2)

struct tm{
int tm_sec; /* Seconds: 0-59 (K&R says 0-61?) */
int tm_min; /* Minutes: 0-59 */
int tm_hour; /* Hours since midnight: 0-23 */
int tm_mday; /* Day of the month: 1-31 */
int tm_mon; /* Months *since* january: 0-11 */
int tm_year; /* Years since 1900 */
int tm_wday; /* Days since Sunday (0-6) */
int tm_yday; /* Days since Jan. 1: 0-365 */
int tm_isdst; /* +1 Daylight Savings Time, 0 No DST,
* -1 don't know */
};

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 16


C - part 2
Câmpuri de biţi (1)
◼ Structurarea datelor la nivel de bit este posibilă, în limbajul C, prin
definirea de câmpuri de biţi. Această facilitate este utilă pentru scrierea
aplicaţiilor de control al dispozitivelor fizice (driver-e) comunicare cu
sisteme industriale, ş.a. Câmpurile de biţi se pot declara ca membri ai
unei structuri astfel:
struct <id_tip> {
<tip_camp_1> <id_camp_1>:lungime_1;
<tip_camp_2> <id_camp_2>:lungime_2;
...
<tip_camp_i> <id_camp_i>:lungime_i;
...
<tip_camp_n> <id_camp_n>:lungime_n;
} <lista identificatori de tip struct>;

◼ Totuşi, pentru câmpurile de biti, <tip_camp_i> poate fi doar int, signed


sau unsigned, lungime_i este o constantă întreagă cu valoarea în
domeniul 0-15 (!).

https://www.tutorialspoint.com/cprogramming/c_bit_fields.htm
Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 17
C - part 2
Câmpuri de biţi (2)
◼ In exemplul:
struct s_bit {
unsigned a:1;
unsigned b:3;
unsigned :4;
unsigned c:3;
unsigned d:2;
} s;
pentru variabila s se vor aloca 16 biţi (numerotaţi 0-
15 ? Vezi diapozitivul următor), care pot fi
accesaţi prin: s.a (bitul 0); s.b (biţii 1-3); s.c (biţii
8-10); s.d (biţii 11,12). Observăm că biţii 4-7 nu
pot fi accesaţi, pentru ei nu s-a specificat nici un
identificator de câmp. Alocarea câmpurilor
poate ridica probleme de
portabilitate, deoarece organizarea
memoriei depinde de sistemul de
calcul (BIG endian, LITTLE endian).

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 18


C - part 2
Sizeof – variabile de tip bit-field

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 19


C - part 2
Câmpuri de biţi – exemple (2)

struct {
unsigned f1 : 4;
unsigned : 3;
signed f2 : 1;
unsigned : 0; /* aliniere */
unsigned f3 : 6;
}sb;

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 20


C - part 2
Câmpuri de biţi – exemple (3)

typedef unsigned int boolean_t;


#define FALSE 0
#define TRUE !FALSE
typedef union {
struct {
boolean_t user:1;
boolean_t zero:1;
boolean_t force:1;
int :28; /* unused */
boolean_t compat:1; /* bit 31 */
};
int raw;
} flags_t;

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 21


C - part 2
Uniuni – union (1)
◼ Uniunile sunt entităţi care pot conţine (la momente de timp diferite) obiecte de tipuri diferite.
Practic, mai multe variabile sunt suprapuse în acelaşi spaţiu de memorie. Sintaxa declaraţiei
este similară cu cea a structurii, dar identificatorii declaraţi ca membri reprezintă numele cu
care sunt referite diferitele tipuri de variabile ce ocupă aceeaşi zonă de memorie:
<declaraţie uniune> ::=
union <id_tip> {
<tip_var_1> <id_var_1>;
<tip_var_2> <id_var_2>;
...
<tip_var_i> <id_var_i>;
...
<tip_var_n> <id_var_n>;
} <lista identificatori de tip union>;
◼ Spaţiul alocat în memorie corespunde tipului cu
dimensiune maximă. Tipurile uniune sunt utile
pentru conversii de date în implementarea
programelor de comunicaţie etc.
Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 22
C - part 2
Uniuni (2)
http://www.cs.utt.ro/~gabia/T
P/2008/L02-UniBiti.htm /*
C: The Complete Reference, 4th Ed. (Paperback)
by Herbert Schildt
ISBN: 0072121246
typedef struct { Publisher: McGraw-Hill Osborne Media; 4 edition (April 26, 2000)
*/

char tip; #include <stdio.h>


#include <stdlib.h>
union cap{
union pw {short int i; char ch[2];};
int nr_locuri; int putw(short int num, FILE *fp);
float tonaj; int main(void){
} capacitate; FILE *fp; fp = fopen("test.tmp", "wb+");
if(fp == NULL) {printf("Cannot open file.\n"); exit(1);}
int km_p; putw(1025, fp); /* write the value 1025 */
char diesel; fclose(fp); return 0;
float consum; }
int putw(short int num, FILE *fp){
} autoturism;
union pw word; word.i = num;
putc(word.ch[0], fp); /* write first half */
return putc(word.ch[1], fp); /* write second half */
}

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 23


C - part 2
Enumerarea constantelor
◼ Tipul enumerare constă dintr-un ansamblu de constante întregi (cel puţin
una), fiecare fiind asociată câte unui identificator. Constanta unui element
al enumerării este fie asociată implicit, fie explicit. Implicit, primul element
are asociată valoarea 0, iar pentru restul are valoarea_precedentă+1.
◼ În limbajul C, valorile asociate identificatorilor pot fi sub controlul total al
programatorului, precum în exemplul:
enum {v1 = -100, v2 = 5, v3 = 7, v4 = -10 };
◼ permitând astfel o nouă metoda de definire a constantelor. Careva
identificatori pot fi initializaţi de către programator urmând ca ceilalţi să
primească valori în urma compilării.

◼ În descrierea
enum {a, b = 6, c, d };
vom avea a = 0, b = 6, c = 7, d = 8.
◼ Componentele de tip enumerare nu pot fi citite de la un mediu
de intrare şi nici afişate deoarece este reţinută numai poziţia
lor în enumerare. Un identificator prezent într-o listă nu poate fi
prezent şi într-o altă listă.
Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 24
C - part 2
Enum – exemplu modificat din …
[http://www.c.happycodings.com/code_snippets/code30.html]
#include <stdio.h>
int main(){
enum Days{Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday};
Days td;
int j = 0;
printf("Please enter the day of the week (0 to 6)\n");
scanf("%d",&j);
td = Days(j);
If (td == Sunday || td == Saturday)
printf("Bla Bla 1\n");
else
printf("Tot la școală\n");
return 0;
}

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 25


C - part 2
Specificatorul typedef
◼ Specificatorul typedef indică faptul că nu se declară o
variabilă sau o funcţie de un anumit tip, ci se asociază
un nume (sinonimul/porecla) tipului de date.
◼ Sintaxa este:
typedef <definiţie tip> <identificator>;
◼ Exemple:
typedef unsigned int natural;
typedef long double tablou [100] ;
tablou a, b, c;
natural m,n,i;
Avatar

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 26


C - part 2
Preprocesare (directive, exemple)

◼ software
multiplatformă,
◼ software multi-
interface

http://www.cs.bilkent.edu.tr/~kdincer/teaching/spring2000/metu-ceng332/lectures/pdf-files/ceng332-chp4.pdf

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 27


C - part 2
Definirea entităților “expandabile”

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 28


C - part 2
#define – exemple (1)

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 29


C - part 2
#DEFINE – exemple (2)
/* Flags for the iobuf structure */
#define _IOREAD 1 /* currently reading */
#define _IOWRT 2 /* currently writing */
#define _IORW 0x0080 /* opened as "r+w" */
#ifndef _FILE_DEFINED
#define _FILE_DEFINED
typedef struct _iobuf{
char* _ptr;
int _cnt;
#ifndef SEEK_SET char* _base;
#define SEEK_SET (0) int _flag;
int _file;
#endif int _charbuf;
int _bufsiz;
#ifndef SEEK_CUR char* _tmpfname;
} FILE;
#define SEEK_CUR (1) #endif /* Not _FILE_DEFINED */
#endif

#ifndef SEEK_END
#define SEEK_END (2)
#endif
Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 30
C - part 2
#include

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 31


C - part 2
Fisier .h utilizator

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 32


C - part 2
Compilare condiționată - sintaxa

◼ Permite crearea de
programe multi-
platformă sau multi-
client
◼ Permite delimitarea
porţiunilor de cod
care se vor compila
când anumite
condiţii sunt
îndeplinite
◼ Notaţie: Prin
newline indicăm
trecerea la rândul
următor, la început.

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 33


C - part 2
Compilare condiționată – exemple

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 34


C - part 2
Alte directive
#include <stdio.h>
#define LINE200 200

int main(void){
func_1(); func_2();
}

#line 100
func_1(){
printf("Func_1 - the current line
number is %d\n",_ _LINE_ _);
}

#line LINE200
func_2(){
printf("Func_2 - the current line
number is %d\n",_ _LINE_ _);
}

Versiunea 2018 G. Albeanu, Fundamentele programării - Limbajul 35


C - part 2

S-ar putea să vă placă și