Domanda

Avere spazi dei nomi sembra come gioco da ragazzi per la maggior parte delle lingue. Ma, per quanto posso dire, ANSI C non lo supporta. Perchè no? Eventuali piani per includere in una futura norma?

È stato utile?

Soluzione

C ha spazi dei nomi. Uno per variabili di struttura, e uno per gli altri tipi. Si consideri la seguente definizione:

struct foo
{
    int a;
};

typedef struct bar
{
    int a;
} foo;

Il primo ha tag foo, e più tardi è fatto in tipo foo con un typedef. Ancora nessun nome-scontro accade. Questo perché variabili di struttura e tipi (tipi built-in tipi e typedef'ed) vivono in spazi dei nomi separati.

Cosa C non consente di creare nuovo namespace per volontà. C è stato standardizzato prima di questa è stata ritenuta importante in una lingua, e gli spazi dei nomi aggiungendo sarebbe anche minacciare retro-compatibilità, perché richiede nome storpiatura di lavoro a destra. Penso che questo può essere attribuito a causa di tecnicismi, non la filosofia.

EDIT: Jeremyp fortunatamente mi ha corretto e ha menzionato gli spazi dei nomi che ho perso. Ci sono spazi dei nomi per le etichette e per la struct / i membri del sindacato pure.

Altri suggerimenti

Per completezza ci sono diversi modi per raggiungere i "benefici" si potrebbe ottenere da spazi dei nomi, in C.

Uno dei miei metodi preferiti sta usando una struttura per ospitare un gruppo di puntatori di metodo che sono l'interfaccia per la libreria / etc ..

È quindi utilizzare un'istanza extern di questa struttura che si inizializza all'interno della vostra punta libreria per tutte le funzioni. Questo consente di mantenere i vostri nomi semplici nella libreria senza calpestare il namespace clienti (diverso da quello della variabile extern in ambito globale, 1 variabile vs forse centinaia di metodi ..)

V'è una certa manutenzione aggiuntiva coinvolti, ma sento che è minima.

Ecco un esempio:

/* 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 */

L'uso di. sintassi crea una forte associazione copre la classica Library_function () Metodo Library_some_value. Ci sono alcune limitazioni tuttavia, per uno non è possibile utilizzare le macro come funzioni.

C ha spazi dei nomi. La sintassi è namespace_name. Si può anche nido come in general_specific_name. E se si vuole essere in grado di nomi di accesso senza scrivere il nome dello spazio dei nomi ogni volta, includere le macro preprocessore rilevanti in un file di intestazione, per esempio.

#define myfunction mylib_myfunction

Questo è molto più pulito di nome mangling e le altre atrocità alcune lingue si impegnano a fornire spazi dei nomi.

Storicamente, compilatori C fanno nomi non mangle (che fanno su Windows, ma la mutilazione per la convenzione di chiamata cdecl è costituito da solo l'aggiunta di un prefisso di sottolineatura).

In questo modo è facile da usare librerie C da altre lingue (tra cui assembler) ed è uno dei motivi per cui si vedono spesso i wrapper per le API extern "C" C ++.

ragioni appena storici. nessuno ha pensato di avere qualcosa di simile a uno spazio dei nomi in quel momento. Inoltre sono stati veramente cercando di mantenere il linguaggio semplice. Possono avere in futuro

Non è una risposta, ma non commento. C non fornisce un modo per definire namespace esplicitamente. Ha portata variabile. Ad esempio:

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);
}

È possibile utilizzare nomi qualificati per le variabili e funzioni:

mylib.h

void mylib_init();
void mylib_sayhello();

L'unica differenza con spazi dei nomi in modo che non si può essere using e non può importare from mylib.

ANSI C è stato inventato prima di namespace erano.

Perché le persone che vogliono aggiungere questa funzionalità per C non hanno ottenuto insieme e organizzati per mettere una certa pressione sulle squadre compilatore autore e sui corpi ISO.

C non supporta gli spazi dei nomi come C ++. L'implementazione di C ++ namespace manipolare i nomi. L'approccio descritto di seguito consente di ottenere il beneficio di namespace in C ++, pur avendo nomi che non sono alterati. Mi rendo conto che la natura della domanda è perché non namespace di supporto C (e una risposta banale sarebbe che non lo fa perché non è stato attuato :)). Ho solo pensato che potrebbe aiutare qualcuno a vedere come ho implementato la funzionalità dei modelli e spazi dei nomi.

Ho scritto un tutorial su come ottenere il vantaggio di spazi dei nomi e / o modelli che utilizzano C.

spazi dei nomi e modelli in C

spazi dei nomi e modelli in C (usando liste concatenate)

Per lo spazio dei nomi di base, si può semplicemente anteporre il nome del namespace come una convenzione.

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

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

può essere scritta come

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 secondo approccio che ho avuto bisogno che utilizza il concetto di namespacing e modelli è quello di utilizzare la concatenazione di macro e comprendono. Ad esempio, posso creare un

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

utilizzando i file di modello come segue

multiply-template.h

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

multiply-template.c

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

Possiamo ora definire int_multiply come segue. In questo esempio, creerò un file 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"

Alla fine di tutto questo, si avrà un file di funzioni e di intestazione per.

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

Ho creato un tutorial molto più dettagliate sui link forniti che mostrano come funziona con le liste concatenate. Speriamo che questo aiuta qualcuno!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top