Frage

Namespaces zu haben scheint wie kein Kinderspiel für die meisten Sprachen. Aber soweit ich kann sagen, nicht ANSI C unterstützt es nicht. Warum nicht? Gibt es Pläne, es in einem zukünftigen Standard enthalten?

War es hilfreich?

Lösung

C hat Namensräumen haben. Ein für Struktur-Tags, und ein für andere Arten. Betrachten Sie die folgende Definition:

struct foo
{
    int a;
};

typedef struct bar
{
    int a;
} foo;

Der erste Teil hat Tag foo, und die später in Typ foo mit einem typedef gemacht. Noch kein Name-Klirren passiert. Dies liegt daran, Strukturvariablen und Typen (integrierte Typen und typedef-Typen) leben in eigenen Namensraum.

Was C nicht erlaubt ist zu erstellen neuen Namensraum durch den Willen. C standardisiert wurde, bevor diese in einer Sprache als wichtig erachtet wurden, und das Hinzufügen von Namespaces würde auch Abwärtskompatibilität gefährden, weil sie Namen Mangeln an der Arbeit Recht erfordert. Ich denke, dies kann aufgrund technischer zurückzuführen, nicht Philosophie.

EDIT: JeremyP korrigiert mich zum Glück und erwähnt die Namespaces ich verpasst. Es gibt Namensraum für Etiketten und für Struktur / Union-Mitglieder als auch.

Andere Tipps

Für Vollständigkeit gibt es mehrere Möglichkeiten, die „Vorteile“ erreichen Sie von Namensräumen bekommen könnte, in C.

Eine meiner Lieblingsmethoden wird mit einer Struktur, die eine Reihe von Verfahren Zeiger zu beherbergen, die die Schnittstelle zu Ihrer Bibliothek sind / etc ..

Sie dann eine externe Instanz dieser Struktur verwenden, die Sie in Ihrer Bibliothek zeigt auf alle Funktionen zu initialisieren. Auf diese Weise können Sie in Ihrer Bibliothek Ihren Namen einfach zu halten, ohne auf den Kunden-Namensraum Schritt (andere als die externe Variable im globalen Bereich, 1 Variable vs möglicherweise Hunderte von Methoden ..)

Es gibt einige zusätzliche Wartung beteiligt, aber ich fühle, dass es minimal ist.

Hier ist ein Beispiel:

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

Die Verwendung von. Syntax erzeugt eine starke Assoziation über die klassische Library_function () Library_some_value Methode. Es gibt jedoch einige Einschränkungen, für die Sie keine Makros als Funktionen verwenden können.

C hat Namespaces. Die Syntax ist namespace_name. Sie können Nest sie wie in general_specific_name glätten. Und wenn Sie den Zugriff auf Namen in der Lage sein möchten, ohne den Namespace-Namen jedes Mal auszuschreiben sind die entsprechenden Präprozessormakros in einer Header-Datei, z.

#define myfunction mylib_myfunction

Das ist viel sauberer als Name Mangeln und die anderen Grausamkeiten bestimmten Sprachen verpflichten Namensraum zu liefern.

Historisch gesehen, C-Compiler nicht mangle Namen (sie tun auf Windows, aber die Mangeln für die cdecl Aufrufkonvention besteht aus nur das Hinzufügen eines Unterstrichs Präfix).

Dies macht es leicht zu bedienen C-Bibliotheken aus anderen Sprachen (einschließlich Assembler) und ist einer der Gründe, warum oft Sie extern "C" Wrapper für C ++ APIs sehen.

nur aus historischen Gründen. Niemand dachte damals so etwas wie ein Namensraum. Auch versuchen sie, die Sprache wirklich einfach zu halten. Sie können es in der Zukunft

Nicht eine Antwort, aber kein Kommentar. C bietet keinen Weg namespace explizit zu definieren. Es verfügt über variable Umfang. Zum Beispiel:

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

Sie können qualifizierte Namen für Variablen und Funktionen zur Verfügung:

mylib.h

void mylib_init();
void mylib_sayhello();

Der einzige Unterschied von Namespaces es, dass Sie nicht using werden können und nicht importieren from mylib.

ANSI C erfunden wurde, bevor Namespaces waren.

Weil die Menschen, die diese Fähigkeit zu C hinzufügen möchten nicht zusammen bekommen und organisiert einen gewissen Druck auf Compiler Autorenteams zu setzen und auf ISO-Gremien.

C unterstützt keine Namensräume wie C ++. Die Implementierung von C ++ Namespaces mangle die Namen. Der Ansatz skizzierte unten können Sie den Nutzen von Namensräumen in C ++ bekommen, während Namen aufweisen, die nicht verstümmelt werden. Mir ist klar, dass die Art der Frage ist, warum nicht C Unterstützung von Namespaces (und eine triviale Antwort wäre, dass dies nicht der Fall, weil es nicht implementiert wurde :)). Ich dachte nur, dass es jemand helfen könnte, um zu sehen, wie ich die Funktionalität von Vorlagen und Namespaces implementiert haben.

schrieb ich ein Tutorial auf, wie die Vorteile der Namensräume zu erhalten und / oder Vorlagen C

Namespaces und Vorlagen in C

Namensräume und Vorlagen in C (mit verketteten Listen)

Für die Grundnamespace, kann man einfach den Namespace-Namen als Konvention voranstellen.

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

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

kann geschrieben werden

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, ... );

Ein zweiter Ansatz, dass ich gebraucht habe, dass nutzt das Konzept des Namespacing und Vorlagen ist die Makro-Verkettung zu verwenden und schließen. Zum Beispiel kann ich ein

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

mit Template-Dateien wie folgt

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

Wir definieren nun int_multiply wie folgt. In diesem Beispiel werde ich eine int_multiply.h / C-Datei erstellen.

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"

Am Ende all dies, werden Sie eine Funktion und Header-Datei für.

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

Ich habe ein viel detaillierteres Tutorial auf die Links zur Verfügung gestellt, die zeigen, wie es mit verknüpften Listen funktioniert. Hoffentlich hilft dies jemand!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top