2010-09-25 17 views
15

Citando here,comprensione namespace C

In C, ci sono due diversi spazi dei nomi dei tipi: uno spazio dei nomi di struct/union/i nomi dei tag enum e uno spazio dei nomi di typedef nomi.

name.c

$ cat name.c 
#include<stdio.h> 

typedef long long long2; 

int long2() { 
    return 4; 
} 

int main() { 

    printf("hello, world!"); 
    return 0; 
} 
$ gcc name.c -o name 
name.c:4: error: 'long2' redeclared as different kind of symbol 
name.c:3: error: previous declaration of 'long2' was here 
$ 

name2.c

$ cat name2.c 
#include<stdio.h> 

int four() { 
    return 4; 
} 

struct dummy { 
    int member; 
}; 

int main() { 

    struct dummy four; 
} 

$ gcc name2.c -o name2 
$ 

Sto cercando di capire il C conflitti di namespace.

  • Nel primo caso, perché c'è un conflitto? Le funzioni appartengono anche al namespace typedef?

  • Nel secondo caso, perché non c'è alcun conflitto? Sia la funzione che la variabile sono denominate quattro. Perché il compilatore lo consente? Come si può risolvere &four?

risposta

20

C dispone di quattro differenti spazi dei nomi per gli identificatori:

  • I nomi delle etichette (il tipo goto).
  • Tag (nomi di strutture, sindacati ed elenchi).
  • Membri di strutture e sindacati (questi hanno uno spazio dei nomi separato per struttura/unione).
  • Tutti gli altri identificatori (nomi di funzioni, nomi di oggetti, nomi di tipo (def), costanti di enumerazione, ecc.).

Vedere anche C99 6.2.3.

Così il vostro due domanda si può rispondere come:

  1. Sì, i nomi delle funzioni e typedef nomi condividono lo stesso spazio dei nomi.
  2. Nessun conflitto, perché il compilatore utilizzerà le regole di ambito (per nomi di funzioni o oggetti). L'identificatore in main è detto shadow il nome della funzione globale, qualcosa che il compilatore ti avviserà se i livelli di avviso vengono impostati abbastanza alti.
+0

Does structs/unions/enum condivide uno spazio dei nomi? cioè, possiamo 'struct T' e' union T' andare bene insieme? – iBug

5

Il tuo secondo esempio non mostra "nessun conflitto". C'è un conflitto! Prova questo:

#include <stdio.h> 
int four(void) { return 4; } 
struct dummy { int member; }; 
int main(void) { 
    struct dummy four; 
    four.member = four(); 
} 

E ora questo

#include <stdio.h> 
int four(void) { return 4; } 
struct dummy { int member; }; 
int main(void) { 
    int (*fx)(void) = four; /* "save" function */ 
    struct dummy four;  /* hide it   */ 
    four.member = fx(); /* use "hidden" fx */ 
} 

Nel vostro secondo esempio, la variabile fourpelli la funzione four().

6

Ma il punto cruciale dei tuoi esempi non riguarda lo spazio dei nomi, ma lo scopo dei nomi.

In name.c, sia long2 sono "identificatori ordinari" (condividere lo stesso spazio dei nomi), ed entrambi sono definiti nello stesso ambito, per cui v'è un conflitto. (C99 § 6,7/3)

Se name2.c, la variabile locale four è in un ambito più profonda della funzione four, quindi le variabili pelli la funzione four (C99 § 6.2.1/4) .