Pregunta

Tener espacios de nombres parece obviedad para la mayoría de los idiomas. Pero por lo que yo puedo decir, ANSI C no lo soporta. Por qué no? ¿Hay planes para incluir en una futura norma?

¿Fue útil?

Solución

C tiene espacios de nombres. Uno para las variables de estructura, y otra para otros tipos. Considere la siguiente definición:

struct foo
{
    int a;
};

typedef struct bar
{
    int a;
} foo;

La primera tiene etiqueta foo, y el posterior está hecho en tipo foo con un typedef. Todavía sin nombre-choque sucede. Esto se debe a que las variables de estructura y tipos (tipos incorporados tipos y typedef'ed) viven en espacios de nombres separados.

Lo que C no permite es crear nueva espacio de nombres por voluntad. C Se normalizó antes de que esto se consideró importante en un idioma, y ??la adición de espacios de nombres también se pondría en peligro la compatibilidad con versiones anteriores, ya que requiere renombrado de nombres a la derecha de trabajo. Creo que esto se puede atribuir debido a tecnicismos, no filosofía.

EDIT: JeremyP afortunadamente me corrigió y mencionó los espacios de nombres que echaba de menos. Hay espacios de nombres para las etiquetas y para struct / miembros de la Unión, así.

Otros consejos

Para completar hay varias maneras de lograr los "beneficios" que podría obtener a partir de espacios de nombres, en C.

Una de mis métodos favoritos está utilizando una estructura para albergar un montón de punteros de métodos que son la interfaz a la biblioteca / etc ..

A continuación, utilice una instancia externo de esta estructura que inicializar el interior de su biblioteca apuntando a todas sus funciones. Esto le permite mantener su nombre simple en su biblioteca sin pisar el espacio de nombres de clientes (que no sea la variable externo al ámbito global, la variable 1 vs posiblemente cientos de métodos ..)

Hay un poco de mantenimiento adicional implicado, pero siento que es mínima.

Este es un ejemplo:

/* interface.h */

struct library {
    const int some_value;
    void (*method1)(void);
    void (*method2)(int);
    /* ... */
};

extern const struct library Library;
/* interface.h */

/* interface.c */
#include "interface.h"

void method1(void)
{
   ...
}
void method2(int arg)
{
   ...
}

const struct library Library = {
    .method1 = method1,
    .method2 = method2,
    .some_value = 36
};
/* end interface.c */

/* client code */
#include "interface.h"

int main(void)
{
    Library.method1();
    Library.method2(5);
    printf("%d\n", Library.some_value);
    return 0;
}
/* end */

El uso de. sintaxis crea una fuerte asociación con respecto al método clásico Library_function () Library_some_value. Hay algunas limitaciones sin embargo, para que usted no puede utilizar las macros como funciones.

C tiene espacios de nombres. La sintaxis es namespace_name. Incluso puede anidar como en general_specific_name. Y si quieres ser capaz de nombres de acceso sin tener que escribir el nombre del espacio de nombres cada vez, incluir las macros del preprocesador relevantes en un archivo de cabecera, por ejemplo.

#define myfunction mylib_myfunction

Esto es mucho más limpio que el renombrado de nombres y las otras atrocidades algunas lenguas se comprometen a ofrecer espacios de nombres.

Históricamente, los compiladores de C no hacer nombres mangle (lo hacen en Windows, pero el planchado de la convención de llamada cdecl consite sólo de la adición de un prefijo de subrayado).

Esto hace que sea fácil de usar bibliotecas de C de otros idiomas (incluyendo el ensamblador) y es una de las razones por las que suelen aparecer envoltorios extern "C" para las API de C ++.

razones que acabamos de históricos. nadie pensó de tener algo así como un espacio de nombres en ese momento. También estaban realmente tratando de mantener la simplicidad del lenguaje. Ellos pueden tener en el futuro

No es una respuesta, pero no un comentario. C no proporciona una manera de definir explícitamente namespace. Tiene alcance variable. Por ejemplo:

int i=10;

struct ex {
  int i;
}

void foo() {
  int i=0;
}

void bar() {
  int i=5;
  foo();
  printf("my i=%d\n", i);
}

void foobar() {
  foo();
  bar();
  printf("my i=%d\n", i);
}

Puede utilizar nombres cualificados para las variables y funciones:

mylib.h

void mylib_init();
void mylib_sayhello();

La única diferencia con respecto a los espacios de nombres que que no puede ser using y no puede from mylib importación.

ANSI C fue inventado antes de espacios de nombres eran.

Debido a que las personas que quieren añadir esta capacidad para C no se han reunido y organizado para poner un poco de presión sobre los equipos compilador y autor de órganos de la ISO.

C no soporta espacios de nombres como C ++. La implementación de espacios de nombres de C ++ mangle los nombres. El enfoque descrito a continuación le permite obtener el beneficio de espacios de nombres en C ++ mientras que tener nombres que no están destrozados. Soy consciente de que la naturaleza de la pregunta es ¿Por qué no C espacios de nombres de apoyo (y una respuesta trivial sería que no lo hace porque no se puso en práctica :)). Sólo pensé que podría ayudar a alguien a ver cómo he implementado la funcionalidad de las plantillas y los espacios de nombres.

Me escribió un tutorial sobre cómo conseguir la ventaja de los espacios de nombres y / o plantillas utilizando C

espacios de nombres y plantillas en C

y espacios de nombres plantillas en C (usando listas enlazadas)

En el espacio de nombres básica, simplemente se puede prefijar el nombre de espacio de nombres como una convención.

namespace MY_OBJECT {
  struct HANDLE;
  HANDLE *init();
  void destroy(HANDLE * & h);

  void do_something(HANDLE *h, ... );
}

se puede escribir como

struct MY_OBJECT_HANDLE;
struct MY_OBJECT_HANDLE *my_object_init();
void my_object_destroy( MY_OBJECT_HANDLE * & h );

void my_object_do_something(MY_OBJECT_HANDLE *h, ... );

Un segundo enfoque que he necesitado que utiliza el concepto de espacios de nombre y las plantillas es usar la concatenación macro e incluyen. Por ejemplo, puedo crear un

template<T> T multiply<T>( T x, T y ) { return x*y }

usando archivos de plantilla de la siguiente manera

multiplicar-template.h

_multiply_type_ _multiply_(multiply)( _multiply_type_ x, _multiply_type_ y);

multiplicar-template.c

_multiply_type_ _multiply_(multiply)( _multiply_type_ x, _multiply_type_ y) {
  return x*y;
}

Ahora podemos definir int_multiply de la siguiente manera. En este ejemplo, voy a crear un archivo int_multiply.h / .c.

int_multiply.h

#ifndef _INT_MULTIPLY_H
#define _INT_MULTIPLY_H

#ifdef _multiply_
#undef _multiply_
#endif
#define _multiply_(NAME) int ## _ ## NAME 

#ifdef _multiply_type_
#undef _multiply_type_
#endif
#define _multiply_type_ int 

#include "multiply-template.h" 
#endif

int_multiply.c

#include "int_multiply.h"
#include "multiply-template.c"

Al final de todo esto, usted tendrá un archivo de función y de cabecera para.

int int_multiply( int x, int y ) { return x * y }

He creado un tutorial mucho más detallada en los enlaces que muestran cómo funciona con listas enlazadas. Espero que esto ayude a alguien!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top