题
对于大多数语言来说,拥有名称空间似乎不费吹灰之力。但是据我所知,ANSI C不支持它。为什么不?有任何计划将其纳入未来的标准中吗?
解决方案
C确实有名称空间。一个用于结构标签,另一种用于其他类型。考虑以下定义:
struct foo
{
int a;
};
typedef struct bar
{
int a;
} foo;
第一个有 标签 foo,后来用TypeDef将其制成foo。仍然没有发生任何名称。这是因为结构标签和类型(内置类型和Typedef'Ed类型)生活在单独的名称空间中。
C不允许创建什么 新的 命名空间由威尔。 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 */
指某东西的用途 。语法在classic 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不支持诸如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);
乘template.c
_multiply_type_ _multiply_(multiply)( _multiply_type_ x, _multiply_type_ y) {
return x*y;
}
现在,我们可以按以下方式定义int_multip。在此示例中,我将创建一个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 }
我在提供的链接上创建了一个更详细的教程,该教程显示了它如何与链接列表一起工作。希望这对某人有帮助!