TITLE: nonequivalence of typedefs and macros (Newsgroups: comp.std.c++, 1 Apr 97) WALTER: icedancer@antispam.ibm.net (Ken Walter) >>A typedef is nothing more than a specialized form of a macro? CLAMAGE: Stephen.Clamage@eng.sun.com (Steve Clamage) I don't agree. Macros operate on the text of the source code before any syntax or semantic analysis occurs. Macros do not obey scope rules. The C++ type system is unknown to macros. Typedefs do not come into play until all macros are fully evaluated. Typedefs obey all scope rules, and are part of the C++ type system. Even these simple examples show some of the differences: #define INT1 int // these lines are typedef int INT2; // not equivalent const INT1 * p1; // non-const pointer to const int const INT2 * p2; // const pointer to non-const int (non-intuitive result) void foo() { #undef INT1 // required to make the next line valid #define INT1 char // error without the #undef typedef char INT2; // ok ... } INT2 i2; // type int -- reverts to outer scope definition INT1 i1; // type char -- retains last definition regardless of scope I think these example also show why you want to avoid using macros. CLAMAGE: Stephen.Clamage@eng.sun.com (Steve Clamage) In article LAA14005@taumet.eng.sun.com, I foolishly wrote: > >#define INT1 int // these lines are >typedef int INT2; // not equivalent > >const INT1 * p1; // non-const pointer to const int >const INT2 * p2; // const pointer to non-const int (non-intuitive result) Abhishek Chauhan was the first, and probably not the last, to point out that I made a mistake here. In this example, p1 and p2 do indeed have the same type. Here is the example as I should have written it, followed by a discussion of what I meant by "counter-intuitive": #define INT1 int* typedef int* INT2; const INT1* p1; // const int** == pointer to (pointer to (const int)) const INT2* p2; // int* const* == pointer to (const (pointer to int)) People sometimes find the resulting type of p2 non-intuitive because they expect the typedef to behave like the macro. It doesn't, and that is why I don't like to say that typedefs are like macros: they are not. If you think of a typedef as creating a type name, which is what it does, you won't make that mistake. If T is a type name, then const T * and T const * mean the same thing: "pointer to const T". Replace T with INT2 and you have the above example. Then replace type INT2 with type int* (which is not the same as replacing text before parsing the type declaration) and you get the translation in the comment. Yes, it seems unnecessarily confusing, but that is the heritage of the C declaration syntax.