并非我曾在我的专业工作中编写如下代码,以下代码是合法的,并在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中的这个合法且明确的含义是C标准的第6.2.3节:
6.2.3标识符的名称空间
如果在翻译单元中的任何点处可见多于一个特定标识符的声明,则句法上下文消除了引用不同实体的用法。因此,各种类别的标识符(标签名称,结构,联合和枚举的标签,结构或联合的成员;以及普通标识符)都有单独的名称空间。
请注意,由于生活在自己名称空间中的标签名称,我可以通过在某处使用标签foo
使代码更加模糊。
添加以下代码并且代码无法编译:
int foo (foo * ptr) {
return ++ptr->foo;
}
所以,有两个问题,一个与C和C ++有关,另一个与C ++相关。
C / C ++问题:为什么我不能定义函数foo
?
我似乎应该能够定义函数foo
;函数名和变量名是“普通标识符”。但如果我添加最后一点代码,我会得到error: redefinition of 'foo' as different kind of symbol
问题:foo * foo;
完全合法,为什么int foo (foo*);
不合法?
C ++问题:这在C ++中是如何工作的?
“名称空间”的含义在C ++中的含义与在C中的含义截然不同。我在C ++标准中找不到任何关于名称空间的C概念的内容,这就是上述内容在C语言中的合法性。
问题:在C ++中这是合法的(章节和诗歌首选)?
答案 0 :(得分:8)
foo * foo;
完全合法,那么为什么intfoo (foo*);
不合法?
因为在与函数相同的声明上下文中已存在名为foo
的类型。您不能在同一范围内拥有同名的类型和函数。
这在C ++中是如何工作的?
因为您可以隐藏嵌套作用域中的名称。当您声明foo * foo
时,第一个foo
引用该类型。第二个foo
声明一个变量 - 此时隐藏了foo
类型。尝试在foo * baz
之后声明foo * foo
,它应该会失败。
struct foo {};
void test() {
foo * foo; // first `foo` is the type, second `foo` is the variable
foo * baz; // first `foo` is the variable
}
答案 1 :(得分:1)
在C ++ 11中,3.3.1 / 4表示在声明性区域中,名称的所有声明都必须引用同一个实体(或重载集)。有一个例外允许你为一组函数名使用类名(所以foo()
隐藏class foo
)但如果你有一个typedef(你这样做),这不适用。
尝试使用C ++中省略的typedef struct foo foo
。
答案 2 :(得分:0)
这在C ++中也不起作用......问题是gcc / g ++的预处理器正在寻找__cplusplus
,而不是cplusplus
。因此你预处理器语句
#if defined FOO && ! defined cplusplus
#undef FOO
#endif
无法正常工作。
答案 3 :(得分:0)
因为已经有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?
}