Having namespaces seems like no-brainer for most languages. But as far as I can tell, ANSI C doesn't support it. Why not? Any plans开发者_如何学运维 to include it in a future standard?
For completeness there are several ways to achieve the "benefits" you might get from namespaces, in C.
One of my favorite methods is using a structure to house a bunch of method pointers which are the interface to your library/etc..
You then use an extern instance of this structure which you initialize inside your library pointing to all your functions. This allows you to keep your names simple in your library without stepping on the clients namespace (other than the extern variable at global scope, 1 variable vs possibly hundreds of methods..)
There is some additional maintenance involved but I feel that it is minimal.
Here is an example:
/* interface.h */
struct library {
const int some_value;
void (*method1)(void);
void (*method2)(int);
/* ... */
};
extern const struct library Library;
/* end 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 client code */
The use of .
syntax creates a strong association over the classic Library_function()
, Library_some_value
method. There are some limitations however, for one you can't use macros as functions.
C does have namespaces. One for structure tags, and one for other types. Consider the following definition:
struct foo
{
int a;
};
typedef struct bar
{
int a;
} foo;
The first one has tag foo, and the later is made into type foo with a typedef. Still no name-clashing happens. This is because structure tags and types (built-in types and typedef'ed types) live in separate namespaces.
What C doesn't allow is to create new namespace by will. C was standardized before this was deemed important in a language, and adding namespaces would also threaten backwards-compatibility, because it requires name mangling to work right. I think this can be attributed due to technicalities, not philosophy.
EDIT: JeremyP fortunately corrected me and mentioned the namespaces I missed. There are namespaces for labels and for struct/union members as well.
C has namespaces. The syntax is namespace_name
. You can even nest them as in general_specific_name
. And if you want to be able to access names without writing out the namespace name every time, include the relevant preprocessor macros in a header file, e.g.
#define myfunction mylib_myfunction
This is a lot cleaner than name mangling and the other atrocities certain languages commit to deliver namespaces.
Historically, C compilers don't mangle names (they do on Windows, but the mangling for the cdecl
calling convention consists of only adding an underscore prefix).
This makes it easy to use C libraries from other languages (including assembler) and is one of the reasons why you often see extern "C"
wrappers for C++ APIs.
just historical reasons. nobody thought of having something like a namespace at that time. Also they were really trying to keep the language simple. They may have it in the future
Not an answer, but not a comment. C doesn't provide a way to define namespace
explicitly. It has variable scope. For example:
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);
}
You can use qualified names for variables and functions:
mylib.h
void mylib_init();
void mylib_sayhello();
The only difference from namespaces it that you cannot be using
and cannot import from mylib
.
ANSI C was invented before namespaces were.
Because people who want to add this capability to C have not gotten together and organized to put some pressure on compiler author teams and on ISO bodies.
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
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!
You can. Like other's answer, define function pointers in a struct.
However, declare it in your header file, mark it static const and initialize it with the corresponding functions. With -O1 or higher it will be optimized as normal function calls
eg:
void myfunc(void);
static const struct {
void(*myfunc)(void);
} mylib = {
.myfunc = myfunc
};
Take advantage of the #include statement so you do not need to define all functions in one single header.
Do not add header guards as you are including it more than once.
eg: 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"
};
精彩评论