Consideracions sobre les variables globals a C99
Continguts
Reglamentació normativa
Resum del que diu l'estàndard C99 sobre compartició de variables i també de http://publications.gbdirect.co.uk/c_book/chapter8/declarations_and_definitions.html
Declaració i definició
Una declaració és una sentència que especifica la interpretació i els atributs d'un conjunt d'identificadors.
Una declaració és també una definició quan:
- En el cas d'un objecte implica la reserva de memòria.
- En el cas d'una funció inclou el cos.
Definició externa
- Una definició externa (ATENCIÓ: no s'ha de confondre amb external linkage) és aquella que té lloc en l'àmbit del fitxer.
No pot haver-hi més d'una definició externa d'un identificador amb linkage intern.
- Una declaració d'un objecte amb inicialitzador en l'àmbit d'un fitxer és una definició externa.
- Una declaració d'un objecte en l'àmbit d'un fitxer que no té inicialització i:
- No té especificador, o bé
Té l'especificador static.
és una definició temptativa.
- Si un fitxer conté una o més definicions temptatives del mateix identificador llavors es comporta com si existís una definició de l'identificador amb un inicialitzador igual a 0.
Linkage
Linkage (6,2,2). Procés a través del qual un identificador declarat en diferents àmbits o declarat més d'una vegada en un sol àmbit pot ésser forçat el mateix objecte o funció. Hi ha tres tipus possibles de linkage:
- Intern. En el context d'un fitxer, tota declaració d'un objecte o
funció amb linkage intern denota la mateixa entitat.
- Extern. En el context dels fitxers que formen un programa, tota
declaracio d'un objecte o funció amb linkage extern denota la mateixa entitat.
Nul. Tot objecte la declaració del qual te linkage nul denota una entitat única.
- Intern. En el context d'un fitxer, tota declaració d'un objecte o
- Tot identificador declarat en l'àmbit d'un fitxer amb l'especificador
'static' té linkage intern.
- Un identificador declarat amb l'especificador 'extern' en qualsevol àmbit que:
- Si l'identificador no tenia cap altra declaració prèvia llavors
aquest identificador té linkage extern.
- Si l'identificador tenia alguna declaració prèvia i no
especificava cap tipus de linkage llavors aquest identificador té linkage extern.
- Si l'identificador tenia una o més declaracions prèvies que
especificaven un linkage extern o intern, llavors aquest identificador té el linkage que s'havia definit prèviament.
- Si l'identificador no tenia cap altra declaració prèvia llavors
Si una funció no té especificador, el seu linkage es determina com si tingués especificador 'extern'.
- La declaració d'un identificador en l'àmbit fitxer es considera que
té linkage extern.
Patrons de treball habituals
Variable global privada d'un mòdul
Patró
Un patró molt corrent és aquell en que en un mòdul d'un programa concret es necessària una variable global en l'àmbit del mòdul però privada de cara a altres mòduls. Habitualment, ho implementem declarant aquesta variable com static en la implementació d'aquest mòdul.
Prenguem com exemple el mòdul modul amb els seus dos fitxers modul.h i modul.c. Suposem que la variable global del mòdul és int a. Llavors aquesta variable la definiriem exclusivament en el fitxer modul.c així:
Rationale
Noteu que la declaració d'a és una 'definició temptativa' i, per tant és com si haguessim usat la definició
1 static int a = 0;
D'altra banda, com està declarat en l'àmbit del fitxer i té el modificador static té linkatge 'intern'. Per tant mai serà compartida per cap altre mòdul.
En conseqüència és una variable global del mòdul i privada d'aquest.
Variable global compartida entre mòduls
Patró
En aquest cas tenim un programa composat de diversos mòduls. Per exemple: m1 i m2. Tenim també una variable global int c que volem compartir entre tots els mòduls però definir només en el mòdul m1. En aquest cas el patró de treball habitual és dissenyar els mòduls de la següent forma:
El mòdul m1:
Pel que fa al mòdul m2:
Rationale
Si analitzem la unitat de compilació del mòdul m1 veiem que, a causa de l'#include, hi ha dues declaracions seguides de la variable c:
extern int c; int c;
La primera és una simple declaració i la segona una definició temptativa, que es consolida com a definició equivalent a int i = 0. D'acord amb al norma, aquesta declaració té linkage 'extern'. Concloent: a m1 es defineix l'objecte c amb linkatge extern.
Si analitzem m2 veiem que només es troba amb la definició extern int c. En aquest cas es tracta d'una declaració (no definició) d'un objecte amb linkage 'extern'.
Considerant ambdós mòduls, tenim una sola definició de c a m1 i dues definicions a m1 i m2 que, en ser amb linkage 'extern', referencien un únic objecte. És a dir, c és un sol objecte compartit entre m1 i m2 i definit a m1.