2010-12-09 102 views
48

對於大多數語言而言,命名空間似乎是不容小覷的。但據我所知,ANSI C不支持它。爲什麼不?是否有計劃將其納入未來的標準?爲什麼ANSI C沒有命名空間?

+8

將C++用作C-with-namespace! – AraK 2010-12-09 08:20:40

+2

我當然可以,但我仍然想知道 – 2010-12-09 08:23:42

+0

@Chris Becke C++命名空間有什麼問題? – AraK 2010-12-09 08:30:41

回答

40

C確實有名稱空間。一個用於結構標籤,另一個用於其他類型。考慮如下定義:

struct foo 
{ 
    int a; 
}; 

typedef struct bar 
{ 
    int a; 
} foo; 

第一個具有標籤 FOO,以及後來被製作成與一個typedef Foo類型。仍然沒有名稱衝突發生。這是因爲結構標籤和類型(內置類型和typedef類型)存在於不同的名稱空間中。

C不允許的是用will創建新的命名空間。 C在語言中被認爲是重要的之前就被標準化了,並且添加命名空間也會威脅向後兼容性,因爲它要求名稱修改才能正常工作。我認爲這可以歸因於技術性,而不是哲學。

編輯: JeremyP幸運地糾正了我,並提到了我錯過的命名空間。標籤和結構/聯合成員也有名稱空間。

6

只是歷史的原因。沒有人想到當時有類似命名空間的東西。此外,他們真的試圖保持語言簡單。他們可能會在將來使用

+1

標準委員會在將來向C添加名稱空間有沒有動作?轉向C/C++模塊可能會使它在未來更容易嗎? – lanoxx 2015-02-13 13:13:30

+1

@lanoxx由於向後兼容的原因,沒有必要向C添加名稱空間。 – themihai 2016-09-06 13:10:38

2

ANSI C是在名稱空間出現之前發明的。

+6

這是?第一個ANSI C規範是1989年。我很確定命名空間(以某種形式或另一種形式)在編程語言之前。例如,Ada於1983年進行了標準化,並將包作爲命名空間。這些反過來基本上是基於Modula-2模塊的。 – 2010-12-09 11:09:26

5

不是一個答案,但不是一個評論。 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唯一的區別。

10

從歷史上看,C編譯器不會破壞名稱(它們在Windows上執行,但對cdecl調用約定的修改只包括添加下劃線前綴)。

這使得使用其他語言(包括彙編程序)的C庫變得非常容易,也是您經常看到C++ API的包裝器的原因之一。

13

C有命名空間。語法是namespace_name。你甚至可以將它們嵌套在general_specific_name中。如果您希望能夠在不每次寫出名稱空間名稱的情況下訪問名稱,請將相關的預處理器宏包含在頭文件中,例如,

#define myfunction mylib_myfunction 

這比名稱修改和其他某些語言提交給命名空間的其他暴行更加清潔。

51

爲了完整有幾種方式來實現「好處」,可能會從命名空間,在C

我最喜歡的方法是使用結構來容納一堆方法指針這是接口的你的圖書館/等等。

然後,您使用此結構的外部實例,該實例在庫中初始化爲指向所有函數。這可以讓你在你的庫中保持你的名字簡單而不需要踩在客戶名稱空間上(除了全局範圍的外部變量,1個變量和可能的數百個方法..)

還有一些額外的維護,但我覺得它是最小的。

下面是一個例子:

/* interface.h */ 

struct library { 
    const int some_value; 
    void (*function1)(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方法上創建了一個強大的關聯。但是有一些限制,因爲你不能使用宏作爲函數。

3

因爲想將這種功能添加到C的人並沒有在一起組織起來對編譯器作者團隊和ISO主體施加壓力。

-2

C不支持像C++這樣的命名空間。 C++名稱空間的實現會破壞名稱。下面概述的方法允許您在C++中獲得名稱空間的好處,同時使名稱不受損壞。我意識到問題的本質是爲什麼C不支持命名空間(並且一個簡單的答案是,它不會因爲它沒有實現:))。我只是認爲它可以幫助某人看到我已經實現了模板和命名空間的功能。

我寫了關於怎樣用C.

Namespaces and templates in C

Namespaces and templates in C (using Linked Lists)

對於基本的命名空間的命名空間和/或模板的優勢的教程,可以簡單地前綴的名稱空間名稱作爲慣例。

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.h我可以創建一個

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

使用模板文件

_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_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 } 

我創建了一個更詳細的教程,提供的鏈接顯示了它如何與鏈接列表一起工作。希望這可以幫助別人!