C语言 为什么 ANSI C 没有命名空间?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4396140/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 07:21:29  来源:igfitidea点击:

Why doesn't ANSI C have namespaces?

cnamespacesansi-c

提问by Pulkit Sinha

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?

对于大多数语言来说,拥有命名空间似乎是不费吹灰之力的。但据我所知,ANSI C 不支持它。为什么不?有没有计划将其包含在未来的标准中?

采纳答案by Pulkit Sinha

C does have namespaces. One for structure tags, and one for other types. Consider the following definition:

C 确实有命名空间。一种用于结构标记,一种用于其他类型。考虑以下定义:

struct foo
{
    int a;
};

typedef struct bar
{
    int a;
} foo;

The first one has tagfoo, 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.

第一个有标签foo,而后一个被做成带有 typedef 的 foo 类型。仍然没有发生名称冲突。这是因为结构标记和类型(内置类型和 typedef 类型)位于不同的命名空间中。

What C doesn't allow is to create newnamespace 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.

C 不允许的是随意创建新的命名空间。C 在这被认为在语言中很重要之前就被标准化了,添加命名空间也会威胁向后兼容性,因为它需要名称修改才能正常工作。我认为这可以归因于技术性,而不是哲学。

EDIT: JeremyP fortunately corrected me and mentioned the namespaces I missed. There are namespaces for labels and for struct/union members as well.

编辑:JeremyP 幸运地纠正了我并提到了我错过的命名空间。标签和结构/联合成员也有命名空间。

回答by guest

For completeness there are several ways to achieve the "benefits" you might get from namespaces, in C.

为了完整起见,有几种方法可以实现您可能从命名空间获得的“好处”,在 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..)

然后使用此结构的外部实例,在指向所有函数的库中初始化该实例。这允许你在你的库中保持你的名字简单,而无需踏入客户端命名空间(除了全局范围内的 extern 变量,1 个变量 vs 可能有数百个方法..)

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;
/* 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 */

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.

指某东西的用途 。语法创建了与经典 Library_function() Library_some_value 方法的强关联。但是,有一些限制,您不能将宏用作函数。

回答by R.. GitHub STOP HELPING ICE

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.

C 有命名空间。语法是namespace_name. 您甚至可以像在general_specific_name. 如果您希望能够访问名称而无需每次都写出名称空间名称,请在头文件中包含相关的预处理器宏,例如

#define myfunction mylib_myfunction

This is a lot cleaner than name mangling and the other atrocities certain languages commit to deliver namespaces.

这比名称修改和某些语言承诺提供命名空间的其他暴行要干净得多。

回答by Christoph

Historically, C compilers don't mangle names (they do on Windows, but the mangling for the cdeclcalling convention consists of only adding an underscore prefix).

从历史上看,C 编译器不会修改名称(它们在 Windows 上会这样做,但是cdecl调用约定的修改仅包括添加下划线前缀)。

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.

这使得使用其他语言(包括汇编器)的 C 库变得容易,这也是您经常看到extern "C"C++ API 包装器的原因之一。

回答by lovesh

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

只是历史原因。当时没有人想过有类似命名空间的东西。此外,他们真的试图保持语言简单。他们可能在未来拥有它

回答by khachik

Not an answer, but not a comment. C doesn't provide a way to define namespaceexplicitly. It has variable scope. For example:

不是答案,但不是评论。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);
}

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 usingand cannot import from mylib.

与命名空间的唯一区别是您不能using也不能导入from mylib

回答by einpoklum

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 的人们还没有聚在一起,没有组织起来对编译器作者团队和 ISO 机构施加一些压力。

回答by Crashworks

ANSI C was invented before namespaces were.

ANSI C 是在命名空间出现之前发明的。

回答by Andy Curtis

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.

C 不支持像 C++ 这样的命名空间。C++ 命名空间的实现会破坏名称。下面概述的方法允许您获得 C++ 中命名空间的好处,同时具有未损坏的名称。我意识到问题的本质是为什么 C 不支持命名空间(一个简单的答案是它不支持,因为它没有实现:))。我只是认为它可能有助于某人了解我是如何实现模板和命名空间的功能的。

I wrote up a tutorial on how to get the advantage of namespaces and/or templates using C.

我写了一篇关于如何使用 C 获得命名空间和/或模板优势的教程。

Namespaces and templates in C

C 中的命名空间和模板

Namespaces and templates in C (using Linked Lists)

C 中的命名空间和模板(使用链表)

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

乘法模板.h

_multiply_type_ _multiply_(multiply)( _multiply_type_ x, _multiply_type_ y);

multiply-template.c

乘法模板.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 如下。在本例中,我将创建一个 int_multiply.h/.c 文件。

int_multiply.h

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

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!

我在提供的链接上创建了一个更详细的教程,这些教程展示了它如何与链表一起工作。希望这对某人有所帮助!