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)?
foo * foo;
is perfectly legal, so why isn't intfoo (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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With