Question

Avoir namespaces semble comme évidence pour la plupart des langues. Mais pour autant que je peux dire, ANSI C ne le supporte pas. Pourquoi pas? Tout projet de l'inclure dans une norme future?

Était-ce utile?

La solution

C n'a namespaces. Une pour les balises de structure, et un pour les autres types. Considérez la définition suivante:

struct foo
{
    int a;
};

typedef struct bar
{
    int a;
} foo;

Le premier a balise foo, et est ensuite transformé en foo de type avec un typedef. Toujours pas de nom-heurt se produit. En effet, les balises de structure et types (types intégrés et types typedef) vivent dans des espaces de noms séparés.

Qu'est-ce que C ne permet pas de créer nouveau espace de noms par testament. C a été normalisée avant cela a été jugé important dans une langue, et en ajoutant namespaces menacerait également la compatibilité ascendante, car il nécessite le nom mutiler au travail à droite. Je pense que cela peut être attribuée en raison de technicités, pas la philosophie.

EDIT: JeremyP heureusement m'a corrigé et a mentionné les namespaces me manquait. Il y a des espaces de noms pour les étiquettes et pour struct / membres du syndicat ainsi.

Autres conseils

Pour être complet, il y a plusieurs façons d'atteindre les « avantages » que vous pourriez obtenir de namespaces, en C.

L'une de mes méthodes préférées utilise une structure pour loger un groupe de pointeurs de méthode qui sont l'interface à votre bibliothèque / etc ..

Vous utilisez ensuite une instance de cette structure extern que vous initialisez l'intérieur de votre pointage bibliothèque pour toutes vos fonctions. Cela vous permet de garder votre nom simple dans votre bibliothèque sans empiéter sur les clients espace de noms (autre que la variable extern à portée globale, 1 variables vs éventuellement des centaines de méthodes ..)

Il y a un peu d'entretien supplémentaire impliqué, mais je pense qu'il est minime.

Voici un exemple:

/* 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'utilisation de. syntaxe crée une forte association sur la méthode Library_some_value Library_function () classique. Il y a certaines limites cependant, pour que vous ne pouvez pas utiliser des macros comme fonctions.

C a des espaces de noms. La syntaxe est namespace_name. Vous pouvez même les nids comme dans general_specific_name. Et si vous voulez être en mesure de noms d'accès sans écrire le nom d'espace de noms à chaque fois, inclure les macros préprocesseur pertinentes dans un fichier d'en-tête, par exemple.

#define myfunction mylib_myfunction

Ceci est beaucoup plus propre que le nom mutiler et les autres atrocités certaines langues engageons à livrer des espaces de noms.

Historiquement, les compilateurs C ne pas les noms Mutilation (ils le font sur Windows, mais le mutiler pour la convention d'appel cdecl ne comprend que l'ajout d'un préfixe underscore).

Cela rend voit facile à utiliser des bibliothèques C dans d'autres langues (y compris assembleur) et est l'une des raisons pour lesquelles vous souvent des emballages de extern "C" pour les API C ++.

juste des raisons historiques. personne n'a pensé à avoir quelque chose comme un espace de noms à ce moment-là. En outre, ils ont été vraiment essayer de garder le langage simple. Ils peuvent avoir à l'avenir

Pas une réponse, mais pas un commentaire. C ne fournit pas un moyen de définir namespace explicitement. Il a une portée variable. Par exemple:

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

Vous pouvez utiliser des noms qualifiés pour les variables et les fonctions:

mylib.h

void mylib_init();
void mylib_sayhello();

La seule différence par rapport à ce que vous namespaces ne peut pas être using et ne peut pas from mylib importation.

ANSI C a été inventé avant namespaces étaient.

Parce que les gens qui veulent ajouter cette capacité à C ont pas obtenu ensemble et organisé pour mettre une certaine pression sur les équipes de l'auteur du compilateur et organes de l'ISO.

C ne supporte pas les espaces de noms comme C ++. La mise en œuvre des C namespaces de mangle les noms. L'approche décrite ci-dessous vous permet d'obtenir le bénéfice de namespaces en C ++ tout en ayant des noms qui ne sont pas déchiquetés. Je me rends compte que la nature de la question est pourquoi ne supporte pas les C namespaces (et une réponse triviale serait que ce ne est pas parce qu'il n'a pas été mis en œuvre :)). Je pensais que cela pourrait aider quelqu'un à voir comment j'ai mis en place la fonctionnalité des modèles et des espaces de noms.

J'ai écrit un tutoriel sur la façon d'obtenir l'avantage des espaces de noms et / ou des modèles à l'aide de C.

espaces de noms et modèles dans C

espaces de noms et modèles en C (en utilisant listes chaînées)

Pour l'espace de noms de base, on peut simplement préfixe le nom d'espace de noms comme une convention.

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

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

peut être écrit comme

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

Une seconde approche que j'ai besoin qui utilise le concept de l'espace de nommage et des modèles est d'utiliser la concaténation macro et comprennent. Par exemple, je peux créer un

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

en utilisant les fichiers de modèle comme suit

multiplication-template.h

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

multiplication-template.c

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

Nous pouvons maintenant définir suit int_multiply comme. Dans cet exemple, je vais créer un fichier 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"

A la fin de tout cela, vous aurez un fichier de fonction et en-tête pour.

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

Je créé un tutoriel beaucoup plus détaillé sur les liens fournis qui montrent comment cela fonctionne avec des listes liées. Espérons que cela aide quelqu'un!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top