How can a same identifier be used for two different things in C & C++?

768 views Asked by At

Sorry, If this type of question already asked on SO, but this is new for me when I tried following simple program.

#include <stdio.h>
void foo()
{
    puts("foo() is invoked");
}
struct foo
{
    int a;
};
int main()
{
    struct foo f={3}; 
    printf("%d\n",f.a);
    foo();
}

Shouldn't we get an error? How it is possible to use same identifier for both function & struct in C & C++? What the C & C++ standard says about this?

2

There are 2 answers

0
John Bode On BEST ANSWER

Tag names (for structs, unions, and enums) occupy a different name space from identifiers (function, object, and typedef names). Tag names are disambiguated by the presence of the struct, union, or enum keywords1.

Note that struct and union member names occupy yet another namespace and are disambiguated in expressions by the use of the . or -> component selection operators, so the following code is legal (if a really bad idea):

struct foo { int foo; };
struct foo foo;
foo.foo = some_value();

The type name struct foo is disambiguated by the presence of the struct keyword, and the member name foo.foo is disambiguated by the presence of the . operator.

Here are the things you cannot do:

  • You cannot use the same tag name for a struct and a union, or a struct and an enum, etc; IOW, you cannot do:
    struct foo { ... };
    enum foo { ... };
    union foo { ... };
    
    in the same code;
  • You cannot use the same name for a typedef name and an object name:
    typedef struct foo { int foo; double bar; } foo;
    foo foo;
    
  • You cannot use the same name for an enumeration constant and an object name:
    enum blurga { foo, bar, bletch } foo;
  • You cannot use the same name for a function name and an object name:
    int foo() { ... }
    int bar()
    {
      int foo = foo();
    }
    


1. I'm assuming this is also the case for the class keyword in C++, but I don't have that reference handy.

0
jwodder On

The name of the type is struct foo; i.e., when referring to the struct, foo is always preceded by struct, so it's unambiguously the struct and not the function. Moreover, since this isn't C++, declaring struct foo does not make foo a name for the type, so a plain foo can only refer to the function. You'll only get problems if you try to do:

typedef struct foo {
    int a;
} foo;