Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding confusing typedef grammar

Consider the following code-snippet

typedef int type;
int main()
{
   type *type; // why is it allowed?
   type *k ;// which type?
}

I get an error 'k' is not declared in this scope. The compiler parses type *k as multiplication between type* and k. Isn't this grammar very confusing?

Why is type *type allowed by the C++ Standard? Because the grammar says so? Why?

like image 625
Prasoon Saurav Avatar asked Dec 13 '11 12:12

Prasoon Saurav


People also ask

What is really a typedef used for?

typedef is a reserved keyword in the programming languages C and C++. It is used to create an additional name (alias) for another data type, but does not create a new type, except in the obscure case of a qualified typedef of an array type where the typedef qualifiers are transferred to the array element type.

How do you define a typedef?

The syntax of typedef is as follows: Syntax: typedef data_type new_name; typedef : It is a keyword. data_type : It is the name of any existing type or user defined type created using structure/union. new_name : alias or new name you want to give to any existing type or user defined type.

Is typedef a declaration or definition?

A typedef declaration is a declaration with typedef as the storage class. The declarator becomes a new type. You can use typedef declarations to construct shorter or more meaningful names for types already defined by C or for types that you have declared.

Can you typedef a typedef?

Typedef cannot be used to change the meaning of an existing type name (including a typedef-name). Once declared, a typedef-name may only be redeclared to refer to the same type again.


3 Answers

type *type; // why is it allowed?

C++11 3.3.2/1 says:

The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any)

So the variable name type is not introduced until after the use of the type name type; the type name is the only available meaning of type during the declarator.

type *k ;// which type?

The local variable name hides the global type name, so that is chosen here. This is described in C++11 3.3.10/1:

A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class.

The fully qualified type name, ::type, is of course still available.

like image 60
Mike Seymour Avatar answered Oct 24 '22 05:10

Mike Seymour


The question is actually about when exactly a variable name is defined as an identifier, and the language determines that it is right after the point in code where the variable is declared:

typedef int type;
int main() {
   type t;   // type refers to ::type
   int       // type still refers to ::type
   type;     // variable declared, this shadows ::type
   type + 1; // type is a variable of type int.
}

There are similar rules in other contexts, and it is just a matter of deciding when identifiers are declared. There are other similar situations, for example in the initialization list of a class:

struct test {
   int x;          // declare member
   test( int x )   // declare parameter (shadows member)
   : x(            // refers to member (parameter is not legal here)
        x )        // refers to parameter
   {};
};

Or in the scope of the identifiers in the definition of member functions:

struct test {
   typedef int type;
   type f( type );
};
test::type         // qualification required, the scope of the return type is
                   // at namespace level
test::f(
         type t )  // but the scope of arguments is the class, no qualification
                   // required.
{}

As of the rationale for the decision, I cannot tell you but it is consistent and simple.

like image 20
David Rodríguez - dribeas Avatar answered Oct 24 '22 04:10

David Rodríguez - dribeas


It is confusing, but this is the only way to get access to type variable. If you want to use type type you can do:

typedef int type;
int main() {
    type *type;
    ::type *k ;
    return 0;
} 

Most of those grammar monstrosities come from backward compatibility with C.

like image 3
elmo Avatar answered Oct 24 '22 05:10

elmo