Linkage in C: non GCC seguire le specifiche C99, o non capisco le specifiche?
Domanda
Sto cercando di capire l'esatto comportamento di identificatori di classe di archiviazione di C99, e alcuni comportamenti GCC sembra non seguire le specifiche, a meno che non mi fraintendere la spec. Da 6.2.2 (2):
Da un'unità di traduzione, ciascuna dichiarazione di un identificatore con collegamento interno denota lo stesso oggetto o funzione.
Tuttavia, ho provato GCC (PowerPC-apple-darwin9-gcc-4.2.1) con il seguente programma:
#include <stdio.h>
static int f() {
static int x = 0;
return x++;
}
static int g() {
static int x = 0;
return x++;
}
int main(int argc, char *argv[]) {
printf("g() = %i\n", g());
printf("g() = %i\n", g());
printf("f() = %i\n", f());
printf("f() = %i\n", f());
return 0;
}
Compilato con -std=c99
, Esso stampa il seguente:
g() = 0
g() = 1
f() = 0
f() = 1
Se ho capito bene le specifiche, si dovrebbe stampare:
g() = 0
g() = 1
f() = 2
f() = 3
Capisco perché GCC dovrebbe discostarsi dalla spec qui, mi chiedo solo se c'è una spiegazione più profonda per questo comportamento.
Soluzione
Il paragrafo successivo, 6.2.2 / 3, è importante:
Se la dichiarazione di una identificatore nell'ambito di file per un oggetto o una funzione contiene l'identificatore della classe di archiviazione statica, l'identificatore ha il collegamento interno.
(si noti la enfatizzato identificatore ambito di file ).
I tuoi variabili statiche x
non hanno ambito di file, hanno la portata di blocco.
Altri suggerimenti
In 6.2.2 (6) si dice:
I seguenti identificatori non hanno alcun legame: [...] un campo di applicazione del blocco identificatore per un oggetto espresso senza extern memorizzazione classe specificatore.
Le variabili statiche sono blocchi identificatori di ambito per gli oggetti, e non sono dichiarati extern
. Pertanto essi non hanno alcun legame, soprattutto non il collegamento interno.