Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Name spaces in c++ and c

Tags:

c++

c

syntax

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)?

like image 432
David Hammen Avatar asked Sep 29 '11 12:09

David Hammen


1 Answers

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
}
like image 133
avakar Avatar answered Sep 30 '22 06:09

avakar