c++ 中的命名空间和c
并不是说我永远会在我的专业工作中编写如下代码,以下代码在 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 functionfoo
; function names and variable names are "ordinary identifiers". But if I add that last little bit of code I geterror: redefinition of 'foo' as different kind of symbol
.
Question:foo * foo;
is perfectly legal, so why isn'tint 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
因为在与您的函数相同的声明上下文中已经存在一个名为
foo
的类型。同一作用域中不能有同名的类型和函数。因为您可以在嵌套范围内隐藏名称。当您声明
foo * foo
时,第一个foo
引用类型。第二个foo
声明了一个变量——此时,类型foo
被隐藏。尝试在foo * foo
之后声明foo * baz
,它应该会失败。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.Because you are allowed to hide names in nested scopes. When you declare
foo * foo
, the firstfoo
refers to the type. The secondfoo
declares a variable -- at that point, the typefoo
is hidden. Try declaringfoo * baz
afterfoo * foo
, it should fail.在 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()
hidesclass 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++.这在 C++ 中也不起作用...问题是 gcc/g++ 的预处理器正在寻找
__cplusplus
,而不是cplusplus
。因此,您的预处理器语句无法正常工作。
This doesn't work in C++ either ... the problem is that the pre-processor for gcc/g++ is looking for
__cplusplus
, notcplusplus
. Therefore you pre-processor statementsdo not work correctly.
因为已经有函数
foo()
它是struct foo
的默认构造函数C 中没有构造函数之类的东西。
专门为 Alan Stokes 编辑:
Because there is already function
foo()
it's a default constructof forstruct foo
There are no such things as constructors in C.
Edit specially for Alan Stokes: