ANSI C에 네임 스페이스가없는 이유는 무엇입니까?
대부분의 언어에서 네임 스페이스를 갖는 것은 당연한 것 같습니다. 그러나 내가 말할 수있는 한 ANSI C는 그것을 지원하지 않습니다. 왜 안돼? 향후 표준에 포함시킬 계획이 있습니까?
C에는 네임 스페이스가 있습니다. 하나는 구조 태그 용이고 다른 하나는 다른 유형용입니다. 다음 정의를 고려하십시오.
struct foo
{
int a;
};
typedef struct bar
{
int a;
} foo;
첫 번째는 foo 태그 가 있고, 나중에는 typedef를 사용하여 foo 유형으로 만들어집니다. 여전히 이름 충돌이 발생하지 않습니다. 이는 구조 태그 및 유형 (내장 유형 및 typedef'ed 유형)이 별도의 네임 스페이스에 있기 때문입니다.
C가 허용하지 않는 것은 의지로 새 네임 스페이스 를 만드는 것입니다. C는 이것이 언어에서 중요하다고 간주되기 전에 표준화되었으며 네임 스페이스를 추가하면 제대로 작동하려면 이름 변경이 필요하기 때문에 이전 버전과의 호환성을 위협 할 수 있습니다. 나는 이것이 철학이 아닌 기술 때문이라고 생각합니다.
편집 : JeremyP는 다행히도 나를 수정하고 내가 놓친 네임 스페이스를 언급했습니다. 레이블 및 struct / union 멤버 용 네임 스페이스도 있습니다.
완전성을 위해 C에서 네임 스페이스에서 얻을 수있는 "이점"을 얻을 수있는 여러 가지 방법이 있습니다.
내가 가장 좋아하는 방법 중 하나는 라이브러리 / 등에 대한 인터페이스 인 여러 메서드 포인터를 수용하는 구조를 사용하는 것입니다.
그런 다음 모든 함수를 가리키는 라이브러리 내부에서 초기화하는이 구조의 extern 인스턴스를 사용합니다. 이를 통해 클라이언트 네임 스페이스를 밟지 않고도 라이브러리에서 이름을 단순하게 유지할 수 있습니다 (전역 범위의 extern 변수 제외, 변수 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 */
. 구문은 고전적인 Library_function () Library_some_value 메서드에 대한 강력한 연관성을 만듭니다. 그러나 몇 가지 제한 사항이 있지만 매크로를 함수로 사용할 수 없습니다.
C에는 네임 스페이스가 있습니다. 구문은 namespace_name
입니다. 에서와 같이 중첩 할 수도 있습니다 general_specific_name
. 매번 네임 스페이스 이름을 작성하지 않고 이름에 액세스 할 수 있도록하려면 헤더 파일에 관련 전 처리기 매크로를 포함합니다.
#define myfunction mylib_myfunction
이것은 이름 맹 글링과 특정 언어가 네임 스페이스를 제공하는 다른 잔학 행위보다 훨씬 더 깔끔합니다.
역사적으로 C 컴파일러는 이름을 변경하지 않습니다 (Windows에서 수행하지만 cdecl
호출 규칙에 대한 맹 글링 은 밑줄 접두사 추가로만 구성됨).
따라서 다른 언어 (어셈블러 포함)의 C 라이브러리를 쉽게 사용할 수 있으며 extern "C"
C ++ API 용 래퍼를 자주 보는 이유 중 하나입니다 .
단지 역사적인 이유. 당시에는 아무도 네임 스페이스 같은 것을 생각하지 않았습니다. 또한 그들은 언어를 단순하게 유지하려고 노력했습니다. 그들은 미래에 그것을 가질 수 있습니다
대답은 아니지만 코멘트는 아닙니다. 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 doesn't support namespaces like C++. The implementation of C++ namespaces mangle the names. The approach outlined below allows you to get the benefit of namespaces in C++ while having names that are not mangled. I realize that the nature of the question is why doesn't C support namespaces (and a trivial answer would be that it doesn't because it wasn't implemented :)). I just thought that it might help someone to see how I've implemented the functionality of templates and namespaces.
I wrote up a tutorial on how to get the advantage of namespaces and/or templates using C.
Namespaces and templates in C (using Linked Lists)
For the basic namespace, one can simply prefix the namespace name as a convention.
namespace MY_OBJECT {
struct HANDLE;
HANDLE *init();
void destroy(HANDLE * & h);
void do_something(HANDLE *h, ... );
}
can be written as
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, ... );
A second approach that I have needed that uses the concept of namespacing and templates is to use the macro concatenation and include. For example, I can create a
template<T> T multiply<T>( T x, T y ) { return x*y }
using template files as follows
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;
}
We can now define int_multiply as follows. In this example, I'll create a int_multiply.h/.c file.
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"
At the end of all of this, you will have a function and header file for.
int int_multiply( int x, int y ) { return x * y }
I created a much more detailed tutorial on the links provided which show how it works with linked lists. Hopefully this helps someone!
참고URL : https://stackoverflow.com/questions/4396140/why-doesnt-ansi-c-have-namespaces
'Program Tip' 카테고리의 다른 글
Oracle 11g에서 + 기호를 사용하여 왼쪽 외부 조인 (0) | 2020.10.11 |
---|---|
지속적 통합 서버 (0) | 2020.10.11 |
Log4J에서 임계 값은 무엇을 의미합니까? (0) | 2020.10.11 |
연관성과 종속성의 차이점은 무엇입니까? (0) | 2020.10.11 |
Scala의 apply () 메서드 매직은 어떻게 작동합니까? (0) | 2020.10.10 |