ANSI C에 네임스페이스가 없는 이유는 무엇입니까?
대부분의 언어에서 네임스페이스를 사용하는 것은 쉬운 일인 것처럼 보인다.하지만 제가 아는 한 ANSI C는 지원하지 않습니다.왜 안 되나요?향후 표준에 포함할 계획이 있습니까?
완성도를 높이기 위해 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 */
. 구문을 사용하면 기존의 Library_function() Library_some_value 메서드에 대한 강력한 연관성이 생성됩니다.다만, 매크로를 기능으로서 사용할 수 없는 제한이 있습니다.
C에는 네임스페이스가 있습니다.하나는 구조 태그용이고 다른 하나는 다른 유형용입니다.다음 정의를 고려하십시오.
struct foo
{
int a;
};
typedef struct bar
{
int a;
} foo;
첫 번째 것은 태그 푸가 있고, 다음 것은 타입 푸가 되어 있습니다.여전히 이름 충돌은 일어나지 않습니다.이는 구조 태그와 유형(빌트인 유형 및 typedef' 유형)이 별도의 네임스페이스에 존재하기 때문입니다.
C가 허락하지 않는 것은 유언으로 새로운 네임스페이스를 작성하는 것입니다.C는 언어에서 중요하다고 간주되기 전에 표준화되었으며, 네임스페이스를 추가하면 이름 망글링이 올바르게 작동하기 위해 하위 호환성이 위협받을 수 있습니다.이것은 철학이 아니라 기술성에 기인한다고 생각합니다.
편집: JeremyP는 다행히 저를 수정하고 제가 놓친 네임스페이스를 언급했습니다.라벨 및 구조/조합원을 위한 네임스페이스도 있습니다.
C에는 네임스페이스가 있습니다.구문은 다음과 같습니다.namespace_name
에 있는 것처럼 둥지를 틀 수도 있습니다.general_specific_name
또한 매번 네임스페이스 이름을 쓰지 않고 이름에 액세스할 수 있도록 하려면 헤더 파일에 관련 프리프로세서 매크로를 포함합니다.
#define myfunction mylib_myfunction
이것은 네임스페이스를 전달하기 위해 특정 언어들이 저지르는 다른 잔혹 행위보다 훨씬 깨끗하다.
C 에서는 ).cdecl
발신자 규약은 밑줄 프리픽스만 추가하는 것으로 구성됩니다).
하면 다른 포함)의C를 쉽게 할 수 , C 라이브러리에는 볼 수 이유 중 .extern "C"
C++ API입니다.
ANSI C는 네임스페이스보다 먼저 발명되었다.
역사적 이유일 뿐이야당시에는 아무도 네임스페이스 같은 걸 가질 생각을 못 했어요.또한 그들은 언어를 단순하게 유지하려고 노력했습니다.그들은 미래에 그것을 가질지도 모른다.
C는 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, ... );
네임스페이스와 템플릿 개념을 사용하는 두 번째 접근법은 매크로 연결과 포함을 사용하는 것입니다.예를 들어, I can't complete를 작성할 수 있습니다.
template<T> T multiply<T>( T x, T y ) { return x*y }
다음과 같이 템플릿 파일 사용
multiply-param.h
_multiply_type_ _multiply_(multiply)( _multiply_type_ x, _multiply_type_ y);
multiply-discl.c
_multiply_type_ _multiply_(multiply)( _multiply_type_ x, _multiply_type_ y) {
return x*y;
}
이제 int_multiply를 다음과 같이 정의할 수 있습니다.이 예에서는 int_multiply.h/.c 파일을 만듭니다.
int_interface.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_interface.c
#include "int_multiply.h"
#include "multiply-template.c"
이 모든 것을 끝내면, 에 대한 함수와 헤더 파일을 갖게 됩니다.
int int_multiply( int x, int y ) { return x * y }
링크 리스트의 동작을 나타내는 링크에 대해서, 보다 상세한 튜토리얼을 작성했습니다.이게 도움이 됐으면 좋겠네요!
답변은 아니지만 코멘트는 아닙니다.는 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
.
C에 이 기능을 추가하고 싶은 사람들이 컴파일러 작성팀과 ISO 본체에 부담을 주기 위해 모여 조직하지 않았기 때문입니다.
넌 할 수 있다.다른 사람의 답변과 마찬가지로 구조에서 함수 포인터를 정의합니다.
단, 헤더 파일에 선언하고 static const로 표시한 후 대응하는 함수로 초기화합니다.-O1 이상일 경우 일반 함수 호출에 맞게 최적화됩니다.
예:
void myfunc(void);
static const struct {
void(*myfunc)(void);
} mylib = {
.myfunc = myfunc
};
#include 문을 활용하면 단일 헤더에 모든 함수를 정의할 필요가 없습니다.
헤더 가드는 여러 번 포함되므로 추가하지 마십시오.
예: header1.h
#ifdef LIB_FUNC_DECL
void func1(void);
#elif defined(LIB_STRUCT_DECL)
struct {
void(*func)(void);
} submodule1;
#else
.submodule1.func = func1,
#endif
mylib.h
#define LIB_FUNC_DECL
#include "header1.h"
#undef LIB_FUNC_DECL
#define LIB_STRUCT_DECL
static const struct {
#include "header1.h"
#undef LIB_STRUCT_DECL
} mylib = {
#include "header1.h"
};
언급URL : https://stackoverflow.com/questions/4396140/why-doesnt-ansi-c-have-namespaces
'IT' 카테고리의 다른 글
MySQL: 포맷된 날짜에 왼쪽 조인 최적화 (0) | 2023.02.06 |
---|---|
PHP에서 어레이를 에코 또는 인쇄하려면 어떻게 해야 합니까? (0) | 2023.02.06 |
새 데이터베이스로 가져온 후 웹 페이지에 이상한 문자가 표시됨 (0) | 2023.01.31 |
PHP의 die()와 exit()의 차이점은 무엇입니까? (0) | 2023.01.31 |
JUnit 테스트 내에서 코드가 실행 중인지 여부를 확인하려면 어떻게 해야 합니까? (0) | 2023.01.31 |