Вопрос

Наличие пространств имен кажется нелегким для большинства языков. Но, насколько я могу судить, ANSI C не поддерживает его. Почему бы и нет? Есть планы включить его в будущий стандарт?

Это было полезно?

Решение

C имеет пространства имен. Один для тегов структуры и один для других типов. Рассмотрим следующее определение:

struct foo
{
    int a;
};

typedef struct bar
{
    int a;
} foo;

У первого есть ярлык Foo, а позже становятся типа Foo с Typedef. По-прежнему нет сбивания имен. Это связано с тем, что структурные теги и типы (встроенные типы и типы типов) живут в отдельных пространствах имен.

Что C не позволяет создавать новый Пространство имен по Уиллу. C был стандартизирован до того, как это было признано важным на языке, и добавление пространств имен также угрожало бы обратной совместимости, потому что это требует, чтобы имя искалелось правильно. Я думаю, что это можно отнести из -за технических деталей, а не философии.

РЕДАКТИРОВАТЬ: Иеремип, к счастью, исправил меня и упомянул пространства имен, которые я пропустил. Существуют пространства имен для ярлыков и для членов Struct/Union.

Другие советы

Для полноты есть несколько способов достижения «преимуществ», которые вы можете получить от пространств имен, в C.

Одним из моих любимых методов является использование структуры для размещения куча указателей методов, которые являются интерфейсом для вашей библиотеки/и т. Д.

Затем вы используете внешний экземпляр этой структуры, который вы инициализируете в вашей библиотеке, указывающей на все ваши функции. Это позволяет вам поддерживать свои имена простыми в вашей библиотеке, не наступая на пространство имен клиентов (кроме внешней переменной на глобальной области, 1 переменная против, возможно, сотни методов ..)

Есть некоторое дополнительное обслуживание, но я чувствую, что оно минимально.

Вот пример:

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

Использование . Синтаксис создает сильную ассоциацию по методу классической библиотеки_функции () библиотеки_SOME_VALUE. Однако есть некоторые ограничения, для одного вы не можете использовать макросы в качестве функций.

C имеет пространства имен. Синтаксис есть namespace_name. Анкет Вы можете даже гнездиться с ними как в general_specific_name. Анкет И если вы хотите иметь возможность получить доступ к именам, не записывая имя пространства имен каждый раз, включите соответствующие макросы препроцессора в файл заголовка, например,

#define myfunction mylib_myfunction

Это намного чище, чем имя, искалеченное, а другие злодеяния обязаны доставлять пространства имен.

Исторически, C, компиляторы C не именами (они делают на окнах, но удивительны для cdecl Вызов конвенции состоит только из добавления нижнего префикса).

Это позволяет легко использовать библиотеки C из других языков (включая ассемблер) и является одной из причин, по которой вы часто видите extern "C" Обертки для API C ++.

Просто исторические причины. Никто не думал о том, чтобы иметь что -то вроде пространства имен в то время. Также они действительно пытались сохранить язык простым. Они могут иметь это в будущем

Не ответ, но не комментарий. C не предоставляет способ определить namespace явно. У него есть переменная область. Например:

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

Вы можете использовать квалифицированные имена для переменных и функций:

mylib.h

void mylib_init();
void mylib_sayhello();

Единственная разница от пространств имен, которым вы не можете быть using и не может импортировать from mylib.

ANSI C был изобретен до того, как пространства имен были.

Потому что люди, которые хотят добавить эту способность к C, не собрались вместе и организовались, чтобы оказать некоторое давление на команды авторов компилятора и на тела ISO.

C не поддерживает пространства имен, такие как C ++. Реализация имен C ++ Mangle имена. Подход, описанный ниже, позволяет вам получить выгоду от пространств имен в C ++, одновременно имея имена, которые не искажаются. Я понимаю, что природа вопроса заключается в том, почему C не поддерживает пространства имен (и тривиальный ответ заключается в том, что это не так, потому что он не был реализован :)). Я просто подумал, что это может помочь кому -то увидеть, как я реализовал функциональность шаблонов и пространств имен.

Я написал учебное пособие о том, как получить преимущество пространств имен и/или шаблонов, используя C.

Пространства имен и шаблоны в c

Пространства имен и шаблоны в C (с использованием связанных списков)

Для основного пространства имен можно просто префикс имени пространства имен в качестве соглашения.

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

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

может быть написан как

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

Второй подход, который мне понадобился, который использует концепцию пространства имен и шаблонов, заключается в использовании макрозатенации и включение. Например, я могу создать

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

Использование шаблонных файлов следующим образом

Умножено-template.h

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

Умножьте Tymplate.c

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

Теперь мы можем определить int_multiply следующим образом. В этом примере я создаю файл 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"

В конце всего этого у вас будет функция и файл заголовка.

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

Я создал гораздо более подробный учебник по предоставленным ссылкам, которые показывают, как это работает со связанными списками. Надеюсь, это кому -то поможет!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top