Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Using typedef to Curb Miscreant Code-3 : Page 3




Full Text Search: The Key to Better Natural Language Queries for NoSQL in Node.js

Date: 1/31/2018 @ 2 p.m. ET

Code Simplification
The typedefs I've shown thus far behave like a #define macro that substitutes a synonym with its actual type. Yet unlike macros, typedefs are interpreted at compile-time, thereby enabling the compiler to cope with textual substitutions that are beyond the preprocessor's capabilities. For example,

typedef int (*PF) (const char *, const char *);

This declaration introduces the type PF as a synonym for 'pointer to function taking two const char * arguments and returning int'. In the following function declaration, the use of this typedef is indispensable:

PF Register(PF pf);

Register() takes a callback function of type PF and returns the address of a function with a similar signature that was previously registered. Take a deep breath. I'm about to show you how this declaration would look without a typedef:

int (*Register (int (*pf)(const char *, const char *))) (const char *, const char *);

Few programmers understand what it means, not to mention its risk of introducing mistakes into such convoluted code. Obviously, the use of a typedef here isn't a prerogative but a must. "OK, but does anyone write such code anyway?" the skeptics among you are probably asking. A quick glance at the <csignal> header file reveals signal(), a function which has a similar interface.

typedef and Storage Specifiers
Surprising as it may sound, typedef is a storage class specifier, just like auto, extern, mutable, static and register. This doesn't mean that typedef actually affects the storage characteristics of an object; it only means that syntactically, typedef declarations look like declarations of static, extern etc., variables. This brings us to trap #2:

typedef register int FAST_COUNTER; //error

This won't compile. The problem is that you can't have multiple storage class specifiers in a declaration. Because the token typedef already occupies the position of a storage class specifier, you can't use register (or any other storage class specifier) in a typedef declaration.

Facilitating Cross-platform Development
typedefs have another important use, namely defining machine-independent types. For example, you can define a floating point type called REAL that has the highest precision available on the target machine:

typedef long double REAL;

On machines that don't support long double, this typedef will look like this:

typedef double REAL;

And on machines that don't even support double:

typedef float REAL;

You can compile applications that use the type REAL on every platform without making any changes to the source file. The only thing that will change is the typedef itself. In most cases, even this tiny change will be totally automatic thanks to the wonders of conditional compilation. Nifty, isn't it? The Standard Library uses typedefs extensively to create such platform-independent types: size_t, ptrdiff_t and fpos_t are a few examples. Likewise, typedefs such as std::string and std::ofstream hide the long and nearly unintelligible template specializations basic_string<char, char_traits<char>, allocator<char> > and basic_ofstream<char, char_traits<char> >, respectively.

Danny Kalev is a system analyst and software engineer with 13 years of experience, specializing in C++ and object-oriented analysis and design. He is a member of the ANSI C++ standardization committee and the author of ANSI/ISO C++ Professional Programmer's Handbook (Que, 1999, ISBN: 0789720221). Reach him at dannykk@inter.net.il.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date