Dlaczego ANSI C nie ma przestrzeni nazw?

Posiadanie przestrzeni nazw wydaje się nie zastanawiać dla większości języków. Ale z tego co wiem, ANSI C go nie wspiera. Dlaczego nie? Jakieś plany włączenia go do przyszłego standardu?

Author: Zero Piraeus, 2010-12-09

9 answers

C ma przestrzenie nazw. Jeden dla znaczników struktury, a drugi dla innych typów. Rozważmy następującą definicję:

struct foo
{
    int a;
};

typedef struct bar
{
    int a;
} foo;

Pierwszy z nich ma tag foo, a późniejszy jest przekształcony w typ foo z typedef. Nadal nie dochodzi do starć z nazwiskami. Dzieje się tak, ponieważ znaczniki i typy struktury (typy wbudowane i typy typedef ' ed) żyją w oddzielnych przestrzeniach nazw.

C nie pozwala na tworzenie nowej przestrzeni nazw za pomocą woli. C został znormalizowany, zanim uznano to za ważne w język i dodawanie przestrzeni nazw zagroziłoby również kompatybilności wstecznej, ponieważ wymaga to manipulowania nazwami, aby działać poprawnie. Myślę, że można to przypisać ze względu na aspekty techniczne, a nie filozofię.

Edytuj: JeremyP na szczęście poprawił mnie i wspomniał o przestrzeniach nazw, które przegapiłem. Istnieją przestrzenie nazw dla etykiet oraz dla członków struct/union.

 69
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-09 19:22:07

Dla kompletności istnieje kilka sposobów osiągnięcia "korzyści", które możesz uzyskać z przestrzeni nazw, w C.

Jedną z moich ulubionych metod jest użycie struktury do przechowywania kilku wskaźników metod, które są interfejsem do twojej Biblioteki/etc..

Następnie używasz zewnętrznej instancji tej struktury, którą inicjalizujesz wewnątrz biblioteki, wskazując na wszystkie twoje funkcje. Pozwala to zachować proste nazwy w bibliotece bez wchodzenia w Przestrzeń nazw klientów (inną niż zmienna extern w zasięgu globalnym, 1 zmienna vs prawdopodobnie setki metod..)

W grę wchodzi dodatkowa konserwacja, ale uważam, że jest ona minimalna.

Oto przykład:

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

Użycie . składnia tworzy silne skojarzenie z klasyczną metodą Library_function () Library_some_value. Istnieją jednak pewne ograniczenia, z których nie można używać makr jako funkcji.

 103
Author: guest,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-20 13:33:46

C ma przestrzenie nazw. Składnia to namespace_name. Można je nawet zagnieżdżać jak w general_specific_name. A jeśli chcesz mieć dostęp do nazw bez każdorazowego wypisywania nazwy przestrzeni nazw, Dołącz odpowiednie makra preprocesora do pliku nagłówkowego, np.

#define myfunction mylib_myfunction

Jest to o wiele czystsze niż manipulowanie nazwami i inne okrucieństwa, które niektóre języki zobowiązują się do dostarczania przestrzeni nazw.

 26
Author: R.. GitHub STOP HELPING ICE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-09 14:18:27

Historycznie kompilatory C nie mangle nazw (robią to w Windows, ale mangling dla cdecl konwencji wywołania polega tylko na dodaniu prefiksu podkreślenia).

Ułatwia to Korzystanie z bibliotek C z innych języków (w tym asemblera) i jest jednym z powodów, dla których często widzisz extern "C" wrappery dla interfejsów API C++.

 12
Author: Christoph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-09 10:44:57

Tylko z powodów historycznych. nikt wtedy nie myślał o posiadaniu czegoś takiego jak przestrzeń nazw. Również oni naprawdę starali się utrzymać język prosty. Mogą mieć go w przyszłości

 7
Author: lovesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-09 08:28:46

Nie odpowiedź, ale nie komentarz. C nie dostarcza sposobu na jawne zdefiniowanie namespace. Ma zmienny zasięg. Na przykład:

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

Możesz używać kwalifikowanych nazw zmiennych i Funkcji:

mylib.h

void mylib_init();
void mylib_sayhello();

Jedyną różnicą od przestrzeni nazw jest to, że nie można być using i nie można importować from mylib.

 6
Author: khachik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-09 08:41:05

ANSI C zostało wynalezione przed przestrzeniami nazw.

 3
Author: Crashworks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-09 08:30:23

Ponieważ ludzie, którzy chcą dodać tę możliwość do C, nie zebrali się i nie zorganizowali, aby wywierać presję na zespoły autorów kompilatorów i na organy ISO.

 3
Author: einpoklum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-01 11:44:41

C nie obsługuje przestrzeni nazw takich jak C++. Implementacja przestrzeni nazw w języku C++ powoduje zmianę nazw. Podejście opisane poniżej pozwala uzyskać korzyści z przestrzeni nazw w C++, mając nazwy, które nie są zniekształcone. Zdaję sobie sprawę, że naturą pytania jest to, dlaczego C nie obsługuje przestrzeni nazw (a trywialną odpowiedzią byłoby to, że nie, ponieważ nie został zaimplementowany :)). Pomyślałem tylko, że może komuś pomóc zobaczyć jak zaimplementowałem funkcjonalność szablonów i przestrzenie nazw.

Napisałem tutorial jak wykorzystać przestrzenie nazw i / lub szablony używając C.

Przestrzenie nazw i szablony w C

Przestrzenie nazw i szablony w C (używając list linkowanych)

Dla podstawowej przestrzeni nazw, można po prostu przedrostek nazwy przestrzeni nazw jako konwencję.

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

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

Można zapisać jako

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

Drugim podejściem, którego potrzebowałem, wykorzystującym koncepcję przestrzeni nazw i szablonów, jest użycie makra konkatenacja i include. Na przykład, mogę utworzyć

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

Używanie plików szablonów w następujący sposób

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

Możemy teraz zdefiniować int_multiply w następujący sposób. W tym przykładzie utworzę int_multiply.h/.plik 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"

Na końcu tego wszystkiego, będziesz miał funkcję i plik nagłówka dla.

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

Stworzyłem znacznie bardziej szczegółowy samouczek na temat podanych linków, które pokazują, jak to działa z połączonymi listami. Mam nadzieję, że to komuś pomoże!

 1
Author: Andy Curtis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-29 23:20:56