c++ 中的命名空间和c

发布于 2024-12-07 14:46:38 字数 1353 浏览 1 评论 0原文

并不是说我永远会在我的专业工作中编写如下代码,以下代码在 c++ 和 c 中是合法的,并且编译时不会出现警告:

#include <stdlib.h>

typedef struct foo { int foo; } foo;

foo * alloc_foo () {
   return (struct foo*) malloc(sizeof(foo));
}   

struct foo * alloc_struct_foo () {
   return (foo*) malloc(sizeof(struct foo));
}   


foo * make_foo1 (int val) {
   foo * foo = alloc_struct_foo (); 
   foo->foo = 0;
   return foo;
}

struct foo * make_foo2 (int val) {
   struct foo * foo = alloc_foo();
   foo->foo = 0;
   return foo;
}

是什么使得此代码在 C 中合法且明确的是第 6.2.3 节C标准:

6.2.3 标识符的命名空间
如果特定标识符的多个声明在翻译单元中的任何一点可见,则语法上下文会消除引用不同实体的使用的歧义。因此,不同类别的标识符(标签名称;结构、联合和枚举的标签;结构或联合的成员;以及普通标识符)有单独的名称空间。

请注意,由于标签名称存在于自己的名称空间中,我可以通过在某处使用标签 foo 使代码更加混乱。

添加以下内容,代码无法编译:

int foo (foo * ptr) {
   return ++ptr->foo;
}   

那么,有两个问题,一个与 C 和 C++ 相关,另一个与 C++ 相关。

  • C/C++ 问题:为什么我无法定义函数 foo
    看来我应该能够定义函数 foo;函数名和变量名是“普通标识符”。但是,如果我添加最后一点代码,我会得到错误:将“foo”重新定义为不同类型的符号
    问题:foo * foo; 完全合法,那么为什么 int foo (foo*); 不合法?

  • C++ 问题:这在 C++ 中是如何工作的?
    “命名空间”的含义在 C++ 中与在 C 中具有相当不同的含义。我在 C++ 标准中找不到任何谈论 C 命名空间概念的内容,这使得上述内容在 C 中合法。
    问题:是什么使得这在 C++ 中合法(首选章节和诗句)?

Not that I would ever write the code like the following in my professional work, the following code is legal and compiles without warnings in c++ and c:

#include <stdlib.h>

typedef struct foo { int foo; } foo;

foo * alloc_foo () {
   return (struct foo*) malloc(sizeof(foo));
}   

struct foo * alloc_struct_foo () {
   return (foo*) malloc(sizeof(struct foo));
}   


foo * make_foo1 (int val) {
   foo * foo = alloc_struct_foo (); 
   foo->foo = 0;
   return foo;
}

struct foo * make_foo2 (int val) {
   struct foo * foo = alloc_foo();
   foo->foo = 0;
   return foo;
}

What makes this legal and unambiguous in C is section 6.2.3 of the C standard:

6.2.3 Name spaces of identifiers
If more than one declaration of a particular identifier is visible at any point in a translation unit, the syntactic context disambiguates uses that refer to different entities. Thus, there are separate name spaces for various categories of identifiers (label names; tags of structures, unions, and enumerations; members of structures or unions; and ordinary identifiers).

Note that thanks to label names living in their own name spaces, I could have made the code even more obfuscated by using a label foo somewhere.

Add the following and the code does not compile:

int foo (foo * ptr) {
   return ++ptr->foo;
}   

So, two questions, one related to C and C++ and the other, C++.

  • C/C++ question: Why can't I define the function foo?
    It seems I should be able to define the function foo; function names and variable names are "ordinary identifiers". But if I add that last little bit of code I get error: redefinition of 'foo' as different kind of symbol.
    Question: foo * foo; is perfectly legal, so why isn't int foo (foo*); legal?

  • C++ question: How does this work at all in C++?
    The meaning of "name space" takes on a rather different meaning on in C++ than in C. I can't find anything in the C++ standard that talks about the C concept of name spaces, which is what makes the above legal in C.
    Question: What makes this legal in C++ (chapter and verse preferred)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

你怎么这么可爱啊 2024-12-14 14:46:38

foo * foo; 完全合法,那么为什么 int foo (foo*); 不合法呢?

因为在与您的函数相同的声明上下文中已经存在一个名为 foo 的类型。同一作用域中不能有同名的类型和函数。

这在 C++ 中是如何工作的?

因为您可以在嵌套范围内隐藏名称。当您声明 foo * foo 时,第一个 foo 引用类型。第二个 foo 声明了一个变量——此时,类型 foo 被隐藏。尝试在 foo * foo 之后声明 foo * baz,它应该会失败。

struct foo {};

void test() {
   foo * foo; // first `foo` is the type, second `foo` is the variable
   foo * baz; // first `foo` is the variable
}

foo * foo; is perfectly legal, so why isn't int foo (foo*); legal?

Because there already is a type named foo in the same declaration context as your function. You cannot have a type and a function of the same name in the same scope.

How does this work at all in C++?

Because you are allowed to hide names in nested scopes. When you declare foo * foo, the first foo refers to the type. The second foo declares a variable -- at that point, the type foo is hidden. Try declaring foo * baz after foo * foo, it should fail.

struct foo {};

void test() {
   foo * foo; // first `foo` is the type, second `foo` is the variable
   foo * baz; // first `foo` is the variable
}
゛时过境迁 2024-12-14 14:46:38

在 C++11 3.3.1/4 中,声明性区域中的所有名称声明必须引用同一实体(或重载集)。有一个例外,允许您使用类名作为一组函数名(因此 foo() 隐藏 class foo),但是如果您有一个typedef (你这样做)。

尝试使用 C++ 中省略的 typedef struct foo foo 来实现。

In C++11 3.3.1/4 says that in a declarative region all declarations of a name must refer to the same entity (or an overload set). There's an exception that allows you to use a class name for a set of function names (so foo() hides class foo) but this doesn't apply if you have a typedef (which you do).

Try it with the typedef struct foo foo omitted in C++.

少跟Wǒ拽 2024-12-14 14:46:38

这在 C++ 中也不起作用...问题是 gcc/g++ 的预处理器正在寻找 __cplusplus,而不是 cplusplus。因此,您的预处理器语句

#if defined FOO && ! defined cplusplus
#undef FOO
#endif

无法正常工作。

This doesn't work in C++ either ... the problem is that the pre-processor for gcc/g++ is looking for __cplusplus, not cplusplus. Therefore you pre-processor statements

#if defined FOO && ! defined cplusplus
#undef FOO
#endif

do not work correctly.

尘曦 2024-12-14 14:46:38

因为已经有函数 foo() 它是 struct foo 的默认构造函数

typedef struct foo 
{ 
int a; 
foo(int val)
:a(val) 
{}
} foo;


int foo(int value)
{
  cout << value <<endl;
}

void main()
{
   foo foovar = foo(50); // constructor foo or function foo?
}

C 中没有构造函数之类的东西。

专门为 Alan Stokes 编辑:

typedef struct foo
    { 
    int a; 
    foo(int val, double val2)
    :a(val) 
    {
      cout << val2 << endl;
    }
    } foo;


    int foo(int value, double val2)
    {
      cout << value << val2 << endl;
    }

    void main()
    {
       some_random_func(foo(50, 1.0)); // constructor foo or function foo?
    }

Because there is already function foo() it's a default constructof for struct foo

typedef struct foo 
{ 
int a; 
foo(int val)
:a(val) 
{}
} foo;


int foo(int value)
{
  cout << value <<endl;
}

void main()
{
   foo foovar = foo(50); // constructor foo or function foo?
}

There are no such things as constructors in C.

Edit specially for Alan Stokes:

typedef struct foo
    { 
    int a; 
    foo(int val, double val2)
    :a(val) 
    {
      cout << val2 << endl;
    }
    } foo;


    int foo(int value, double val2)
    {
      cout << value << val2 << endl;
    }

    void main()
    {
       some_random_func(foo(50, 1.0)); // constructor foo or function foo?
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文