typedef
This article needs attention from an expert on the subject. See thetalk page for details. Consider associating this request with a WikiProject. (July 2011) |
This article needs additional citations for verification. Please help improve this article by adding citations to reliable sources. Unsourced material may be challenged and removed. (July 2011) |
typedef
is a
keyword in the
C and
C++
programming languages. The purpose of typedef
is to assign alternative names to existingtypes, most often those whose standard declaration is cumbersome,
potentially confusing, or likely to vary from one implementation to another.[1]
Under C convention (such as in the
C standard library), types declared with typedef end with '_t' (e.g.,
size_t,
time_t).
Contents[hide] |
[edit]Usage examples
[edit]Indicating
what a variable represents
A typedef can be used to indicate how a variable represents something, e.g., units of measurement or counts:
int current_speed ; int high_score ; ... void congratulate(int your_score) { if (your_score > high_score) ...
Now consider this:
typedef int km_per_hour ; typedef int points ; km_per_hour current_speed ; points high_score ; ... void congratulate(points your_score) { if (your_score > high_score) ...
Both sections of code do the same thing. However, the use of typedef
in the second example makes it clear that the two variables, while represented by the same data type (int
), represent different and incompatible things. The declaration
in congratulate()
of your_score
indicates to the programmer thatcurrent_speed
(or any other variable not declared as a
points
) should not be passed as an argument. This would not be as apparent if both were declared asint
s. However, note that the indication is
for the programmer only; the C/C++ compiler considers both variables to beint
s and will not give any type mismatch warnings or errors for the "wrong" argument type forcongratulate(points your_score)
in the code snippet below:
void foo() { km_per_hour km100 = 100; congratulate(km100); ...
[edit]Simplifying
a declaration
A typedef can be used to simplify the declaration for a compound type (struct, union) or pointer type such as:
struct var { int data1; char data2; };
Here (above) a struct var data type has been defined. To declare a variable of this type in C (below) thestruct
key word is required (though it can be omitted in C++):
struct var a;
A typedef can be used to eliminate the need for the struct
key word in C. For example, with:
typedef struct var newtype;
we can now create a variable of this type with:
newtype a;
Note that the structure definition and typedef can instead be combined into a single statement:
typedef struct var { int data1; char data2; } newtype;
Or simply we can also use it as:
typedef struct { int data1; char data2; } newtype;
In
C++, in contrast to C, the struct
, class
, and
key words are optional in variable declarations that are separate from the definitions:
enum
struct var x; // This is legal var y; // This is also legal
As such, var
can be used wherever newtype
can be used. However, the reverse is not true; for instance, the constructor methods forvar
cannot be named
newtype
.
[edit]Using
typedef with pointers
Typedefs can also simplify declarations for
pointer types. Consider this:
struct Node { int data; struct Node *nextptr; };
In C, one can declare multiple variables of the same type in a single statement, even mixing pointer and non-pointers. However, one would need to prefix an asterisk to each variable to designate it as a pointer:
struct Node *startptr, *endptr, *curptr, *prevptr, errptr, *refptr;
A programmer would assume that errptr
was indeed a Node *
, but a typographical error means thaterrptr
is a
Node
. This can lead to subtle syntax errors.
By defining a Node *
typedef, it is assured that all the variables will be pointer types.
typedef struct Node *NodePtr; ... NodePtr startptr, endptr, curptr, prevptr, errptr, refptr;
[edit]Using
typedef with type casts
A typedef is created using type declaration syntax but can be used as if it were created using typecast syntax. (Type casting changes a
data type.) For instance, in each line after the first line of:
typedef int (*funcptr)(double); // pointer to function of double returning int funcptr x = (funcptr) NULL; // C or C++ funcptr y = funcptr(NULL); // C or C++ funcptr z = static_cast<funcptr>(NULL); // C++ only
funcptr
is used on the left-hand side to declare a variable and is used on the right-hand side to cast a value. Thus, typedefs can be used by programmers who do not wish to figure out how to convert declaration syntax to type cast syntax.
Note that, without the typedef, it is generally not possible to use declaration syntax and cast syntax interchangeably. For example:
void *p = NULL; int (*x)(double) = (int (*)(double)) p; // This is legal int (*)(double) y = (int (*)(double)) p; // Left-hand side is not legal int (*z)(double) = (int (*p)(double)); // Right-hand side is not legal
[edit]Usage concerns
Some people are opposed to the extensive use of typedefs. Most arguments center on the idea that typedefs simply hide the actual data type of a variable. For example,Greg
Kroah-Hartman, a
Linux kernel hacker and documenter, discourages their use for anything except function prototype declarations. He argues that this practice not only unnecessarily obfuscates code, it can also cause programmers to accidentally misuse large structures thinking
them to be simple types.[2]
Others argue that the use of typedefs can make code easier to maintain.
K&R states that there are two reasons for using a typedef. First, it provides a means to make a program more portable. Instead of having to change a type everywhere it appears throughout the program's source files, only a single typedef statement needs
to be changed. Second, a typedef can make a complex declaration easier to understand.
[edit]Usage in C++
In C++ type names can be very complicated and typedef provides a mechanism to assign a simple name to the type. Consider:
std::vector<std::pair<std::string, int> > values; for (std::vector<std::pair<std::string, int> >::const_iterator i = values.begin(); i != values.end(); ++i) { std::pair<std::string, int> const & t = *i; // do something }
and
typedef std::pair<std::string, int> value_t; typedef std::vector<value_t> values_t; values_t values; for (values_t::const_iterator i = values.begin(); i != values.end(); ++i) { value_t const & t = *i; // do something }
[edit]Use with
C++ templates
There is no direct way to have templated typedefs in C++. For instance, to havestringpair<T>
represent
std::pair<std::string, T>
for every typeT
one
cannot use:
template<typename T> typedef std::pair<std::string, T> stringpair<T>; // Doesn't work
However, if one is willing to accept stringpair<T>::foo
, or similar, in lieu ofstringpair<T>
then it is possible to achieve the desired result via a typedef within an otherwise unused templatedclass
or struct
:
template<typename T> class stringpair { private: // Prevent instantiation of stringpair<T> stringpair(void) {}; public: // Make stringpair<T>::foo represent std::pair<std::string, T> typedef std::pair<std::string, T> foo; };
[edit]Other languages
In many statically-typed functional languages, like
Haskell,
Miranda,
OCaml, etc., you can define type synonyms, which are the same as typedefs in C. An example in Haskell:
type PairOfInts = (Int, Int)
This example has defined a type synonym "PairOfInts" which means the same as a pair of Ints.
C# also contains a feature which is similar to the typedef of C; however, it must be redeclared for each separate file.See
this MSDN article for more
using newType = global::System.Runtime.Interop.Marshal; using otherType = Enums.MyEnumType;
[edit]See also
[edit]References
- ^Typedef
as a Synonym, It allows you to introduce synonyms for types which could have been declared some other way. - ^Kroah-Hartman,
Greg (2002-07-01)."Proper Linux Kernel Coding Style".
Linux Journal. Retrieved 2007-09-23. "Using a typedef only hides the real type of a variable."