entendiendo los espacios de nombres C

Citando desde aquí ,

En C, hay dos espacios de nombres diferentes de tipos: un espacio de nombres de struct / union / enum tag names y un namespace de typedef names.

name.c

$ cat name.c #include 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 int four() { return 4; } struct dummy { int member; }; int main() { struct dummy four; } $ gcc name2.c -o name2 $ 

Intento entender los conflictos del espacio de nombres de C.

  • En el primer caso, ¿por qué hay un conflicto? ¿Las funciones también pertenecen al espacio de nombres typedef?

  • En el segundo caso, ¿por qué no hay conflicto? La función y la variable se nombran cuatro. ¿Por qué el comstackdor lo permite? ¿Cómo se supone que se resolverán las &four ?

C tiene cuatro espacios de nombres diferentes para identificadores:

  • Nombres de etiqueta (el tipo de goto ).
  • Etiquetas (nombres de estructuras, uniones y enumeraciones).
  • Miembros de estructuras y sindicatos (estos tienen un espacio de nombres separado por estructura / unión).
  • Todos los demás identificadores (nombres de funciones, nombres de objetos, nombres de tipo (def), constantes de enumeración, etc.).

Ver también C99 6.2.3.

Entonces sus dos preguntas pueden ser respondidas como:

  1. Sí, los nombres de funciones y los nombres typedef comparten el mismo espacio de nombre.
  2. No hay conflicto, porque el comstackdor usará reglas de scope (para nombres de funciones o objetos). Se dice que el identificador en main sombrea el nombre de la función global, algo sobre lo que el comstackdor le advertirá si establece los niveles de advertencia lo suficientemente altos.

Pero el punto crucial en sus ejemplos no es sobre el espacio de nombres, sino el scope de los nombres.

En name.c , ambos long2 son “identificadores ordinarios” (comparten el mismo espacio de nombre), y ambos están definidos en el mismo ámbito, por lo que hay un conflicto. (C99 §6.7 / 3)

Si name2.c , la variable local four está en un scope más profundo que la función four , entonces la variable oculta la función four (C99 §6.2.1 / 4).

Su segundo ejemplo no muestra “sin conflicto”. Hay un conflicto! Prueba esto:

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

Y ahora esto

 #include  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 */ } 

En su segundo ejemplo, la variable four oculta la función four() .