Name spaces in c++ and c

生来就可爱ヽ(ⅴ<●) 提交于 2021-01-27 01:46:32

问题


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


回答1:


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
}



回答2:


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++.




回答3:


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.




回答4:


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


来源:https://stackoverflow.com/questions/7597634/name-spaces-in-c-and-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!