Directive preprocesor si metodologie de programare
=======================================
----- ----- -----------------
Folosirea lui #include
----- ----- -----------------
Am discutat deja folosirea directivelor de preprocesare
#include <stdio.h>
#include <stdlib.h>
O alta forma pentru #include este
#include "nume_fisier"
Preprocesorul va inlocui aceasta linie cu o copie a fisierului precizat. Mai intai cautarea se face in directorul curent, apoi
in alte locuri depende 212o148c nte de sistem. Daca directiva este de forma
#include <nume_fisier>
atunci preprocesorul va cauta in alte locuri (deci nu in directorul curent). De exemplu, sub UNIX, fisierele header standard (cum ar fi "stdio.h", "stdlib.h") se gasesc de obicei in directorul
/usr/include
Sub MS-DOS, aceste fisiere se gasesc in directorul
/include
----- ----- ----------------
Folosirea lui #define
----- ----- ----------------
Directivele de preprocesare declarate cu "#define" au doua forme:
- #define identificator sir_atomi
- #define identificator(id,...,id) sir_atomi
O definitie lunga (care nu dorim sa o scriem pe aceeasi linie poate fi continuata pe linia urmatoare punand un \ (backslash) la sfarsitul liniei curente). In primul caz, compilatorul va inlocui fiecare aparitie a "identificatorului" prin "sir_atomi" in restul fisierului (de la pozitia curenta in jos) cu exceptia celor care sunt incadrate intre ghilimele sau apostroafe.
-----------
Exemple:
-----------
#define NR_SEC_PE_ZI (60 * 60 * 24)
#define PI 3.141592653
#define C 299792.458 /* viteza luminii in km/sec */
#define EOF (-1) /* valoarea uzuala pt sfarsit de fisier */
#define MAXINT /* numarul intreg maxim pe 4 octeti */
#define DIMENS 250 /* dimensiunea unui sir */
#define EPSILON 1.0e-9 /* limita numerica */
Deci, folosirea lui "#define" mareste claritatea si portabilitatea unui program.
----- ----- ----------
Sintaxa "dulce"
----- ----- ----------
Se foloseste pentru evitarea unor greseli frecvente sau ca un moft.
------------
Exemplu: #define EQ ==
------------
Aceasta declaratie ajuta programatorul sa nu mai confunde = cu ==.
------------
Exemplu: #define do /* spatiu */
------------
De exemplu, acum putem simula instructiunea "while" din C ca un "while do" din Pascal sau Algol.
De exemplu, daca avem definitiile de sintaxa "dulce" de mai sus, putem spune ca instructiunile
while (i EQ 1) do
si
while (i == 1)
sunt echivalente.
----- ----- --------- ----- ------
Macrouri cu argumente
----- ----- --------- ----- ------
Revenim la forma a doua a macrourilor cu argumente:
#define identificator(id,...,id) sir_atomi
------------
Exemplu: #define SQ(x) ((x) * (x))
------------
Identificatorul x din #define este un parametru care va fi substituit in textul ce urmeaza. Substitutia se face fara considerarea
corectitudinii sintactice. De exemplu,
SQ(7 + w) este echivalent cu ((7 + w) * (7 + w))
Intr-o maniera similara,
SQ(SQ(*p)) este echivalent cu ((((*p) * (*p))) * (((*p) * (*p))))
Observati deci ca folosirea parantezelor (de exemplu, (x)) are o importanta deosebita, altfel nu s-ar respecta ordinea de evaluare.
----- ----- ---------------
Unde este greseala ? #define SQ(x ((x) * (x));
----- ----- ---------------
Macrourile sunt folosite de obicei pentru a inlocui apelurile functiilor cu cod liniar (scurte si fara variabile suplimentare).
-----------
Exemplu: Macroul de mai jos defineste minimul a doua valori:
-----------
#define min(x, y (((x) < (y)) ? (x (y))
Dupa aceasta definitie, o expresie de forma
m = min(u, v)
se poate expanda de catre preprocesor la
m = (((u) < (v) (u (v))
Folosind aceasta definitie, putem defini minimul a patru valori, astfel
#define min4(a, b, c, d) min(min(a,b), min(c, d))
O macro-definitie poate folosi functii si macrouri in corpul lor.
-----------
Exemple:
-----------
#define SQ(x) ((x) * (x))
#define CUB(x) (SQ(x) * (x))
#define F_POW(x sqrt(sqrt(CUB(x)))
O directiva de preprocesare de forma
#undef identificator
va anula definitia precedenta a identificatorului.
-------- ----- ------ ----- ----- --------------
Definitii de tipuri si macrouri din <stddef.h>
-------- ----- ------ ----- ----- --------------
C pune la dispozitie facilitatea "typedef" pentru a asocia (redenumi) un tip cu unul specific.
-----------
Exemplu: typedef char uppercase;
-----------
Declaratia de mai sus face tipul "uppercase" sinonim cu "char". De exemplu, declaratiile de mai jos sunt valide:
uppercase c, u[100];
Fisierul header <stddef.h> contine cateva definitii de tip:
typedef int ptrdiff_t; /* tip intors de diferenta pointerilor */
typedef short wchar_t; /* tip caracter mare */
typedef unsigned size_t; /* tipul sizeof */
Tipul "ptrdiff_t" spune care este tipul returnat de o expresie implicata in diferenta a doi pointeri. In MS-DOS, acesta depinde de modelul de memorie ales (tiny, short, large, far, huge), pe cand in UNIX, tipul folosit este "int".
Tipul "wchar_t" se foloseste pentru acele caractere care nu se pot reprezenta pe un octet (char -> int).
Reamintim ca operatorul "sizeof" este folosit pentru determinarea lungimii unui tip sau a unei expresii. De exemplu, "sizeof(double) = 8". Tipul "size_t" este returnat de operatorul "sizeof".
Un macrou definit in <stddef.h> este
#define NULL 0
|