is a reserved keyword in the programming languages C, C++, and Objective-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. As such, it is often used to simplify the syntax of declaring complex data structures consisting of struct and union types, although it is also commonly used to provide specific descriptive type names for integer data types of varying sizes.

Syntax A typedef declaration follows the same syntax as declaring any other C identifier. The keyword typedef itself is a specifier which means that while it typically appears at the start of the declaration, it can also appear after the type specifiers or between two of them.

In the C standard library and in POSIX specifications, the identifier for the typedef definition is often suffixed with , such as in size_t and time_t. This is practiced in some other coding systems, although POSIX explicitly reserves this practice for POSIX data types. In C++, this suffix is not used for typedefs (as C++ does not mandate prefixing structs with the struct keyword), but does appear in some types in the C++ Standard Library (especially for tag types, like std::in_place_t) along with other suffixes like (typically representing an abbreviation for a T::value field).

Examples This snippet declares the type as an alias of the type , allowing a user to use as a type in declarations where they would otherwise use :typedef int Length;

Length my_length = 3; // my_length is type 'int'

Documentation use A typedef declaration may be used to give more contextual meaning than is given by the underlying type, hinting to the user of functions or variables a certain meaning or format is expected. For example, in the code below, the type is being further clarified to the distinct aliases and :

typedef int KmPerHour; typedef int Points;

KmPerHour top_speed; Points high_score;

void congratulate(Points your_score, KmPerHour your_top_speed) { if (your_score > high_score) { // ...

if (your_top_speed > top_speed) { // ...

The use of typedef here is used to indicate that only variables declared as (or variables that can be interpreted as a type) should be used as the first argument, and variables declared as for the second. The value of using typedef in this manner would be for specific cases where masking the underlying type with an alias would add substantial clarity for the programmer, and not for any sort of type enforcement from the compiler, since typedefs are translated back to underlying types before any error checking occurs. For example, this code will compile, without any error:

void foo() { KmPerHour my_top_speed = 100; // compiler: type is 'int' Points my_score = 5000; // compiler: type is 'int'

congratulate(my_score, my_top_speed); // compiler: arguments are (int, int) congratulate(my_top_speed, my_score); // compiler: arguments are (int, int) }

Declaration simplification A typedef may be used to simplify the declarations of objects having types with verbose names, such as struct, union, or enum types. The point of this is to make it more convenient to declare variables with certain types. For example,

struct NamedLocation { float x; float y; char *name;

// normal declaration struct NamedLocation location_a;

// declares NamedLocationType as an alias to the type 'struct NamedLocation' typedef struct NamedLocation NamedLocationType;

NamedLocationType location_b; // type is 'struct NamedLocation'

Along with providing previously declared types directly after the keyword, one may also put a full definition of a struct, union, or enum. This has the effect of providing both a type definition and an alias in one statement.

typedef enum Weather { CLOUDY, RAINY, SUNNY } WeatherType;

enum Weather yesterdays_weather; WeatherType todays_weather;

When a definition is provided in the typedef declaration, the tag (i.e. name of the underlying type) is optional, leaving only the alias. Modifying the previous snippet:

typedef enum { CLOUDY, RAINY, SUNNY } WeatherType;

enum Weather yesterdays_weather; // ERROR: "enum Weather" does not exist. WeatherType todays_weather; // OK

In C++, unlike in C, the tag of a , , , or type is called a class name, and can be used as a type alias automatically without any typedef declaration.

struct MyStruct { int value1; char value2;

typedef struct MyStruct MyNewType;

struct MyStruct x; // OK in C/C++ MyNewType y; // OK in C/C++ MyStruct z; // OK in C++, error in C

The correspondence between this C++ feature and typedef is very strong, extending to the fact that it is possible to shadow the simple type name in a nested scope by declaring it as the identifier of another kind of entity. In such a case, the C-style full type name (an "elaborated type specifier") can still be used to refer to the class or enum type.

In C++, then, can be used anywhere that can be used, as long as there are no other declarations of these identifiers. The reverse is not true, however, for C++ requires the class name for some purposes, such as the names of constructor methods.

A notorious example where even C++ needs the keyword is the POSIX stat system call that uses a struct of the same name in its arguments:

int stat(const char* filename, struct stat* buf) { // ... }

Here both C as well as C++ need the keyword in the parameter definition.

Pointers The typedef may be used to define a new pointer type.

typedef int* IntPtr;

IntPtr ptr;

// Same as: // int* ptr;

is a new alias with the pointer type . The definition, , defines a variable with the type . So, is a pointer which can point to a variable of type .

Using typedef to define a new pointer type may sometimes lead to confusion. For example:

typedef int* IntPtr;

// Both 'cliff' and 'allen' are of type int*. IntPtr cliff, allen;

// 'cliff2' is of type int*, but 'allen2' is of type int**. IntPtr cliff2, *allen2;

// Same as: // IntPtr cliff2; // IntPtr* allen2;

Above, means defining 2 variables with type for both. This is because a type defined by typedef is a type, not an expansion. In other words, , which is the type, decorates both and . For , the type decorates the and . So, is equivalent to 2 separate definitions, and . means that is a pointer pointing to a memory with type. Shortly, has the type, .

Constant pointers

Again, because typedef defines a type, not an expansion, declarations that use the const qualifier can yield unexpected or unintuitive results. The following example declares a constant pointer to an integer type, not a pointer to a constant integer:

typedef int* IntPtr;

const IntPtr ptr = nullptr;

// This is equivalent to: // int* const ptr = nullptr; // Constant pointer to an integer.

Since it is a constant pointer, it must be initialized in the declaration.

Structures and structure pointers Typedefs can also simplify definitions or declarations for structure pointer types. Consider this:

struct Node { int data; struct Node* next;

Using typedef, the above code can be rewritten like this:

typedef struct Node Node;

struct Node { int data; Node* next;

In C, one can declare multiple variables of the same type in a single statement, even mixing structure with pointer or non-pointers. However, one would need to prefix an asterisk to each variable to designate it as a pointer. In the following, a programmer might assume that was indeed a , but a typographical error means that is a . This can lead to subtle syntax errors.

struct Node *startptr, *endptr, *curptr, *prevptr, errptr, *refptr;

By defining the typedef , it is assured that all variables are structure pointer types, or say, that each variable is a pointer type pointing to a structure type.

typedef struct Node* NodePtr;

NodePtr startptr, endptr, curptr, prevptr, errptr, refptr;

Function pointers int do_math(float arg1, int arg2) { return arg2; }

int call_a_func(int (*call_this)(float, int)) { int output = call_this(5.5, 7);

return output; }

int final_result = call_a_func(&do_math);

The preceding code may be rewritten with typedef specifications:

typedef int (*MathFunc)(float, int);

int do_math(float arg1, int arg2) { return arg2; }

int call_a_func(MathFunc call_this) { int output = call_this(5.5, 7);

return output; }

int final_result = call_a_func(&do_math);

Here, is the new alias for the type. A is a pointer to a function that returns an integer and takes as arguments a float followed by an integer.

When a function returns a function pointer, it can be even more confusing without typedef. The following is the function prototype of signal(3) from FreeBSD:

void (*signal(int sig, void (*func)(int)))(int);

The function declaration above might be mildly cryptic to a few people as it might be slightly difficult for a reader to determine what the function accepts as arguments or the type that it returns. In plain English, it could be described as "a function that takes a first argument of an integer and a second argument of a pointer to a function that itself takes an argument of an integer and returns nothing, and returns a pointer to a function that itself takes an argument of an integer and returns nothing". With typedefs, it can be written slightly more cleanly:

// Typedef found in <signal.h> typedef void (*sighandler_t)(int);

sighandler_t signal(int sig, sighandler_t func);

Arrays A typedef can also be used to simplify the definition of array types. For example,

typedef char ArrType;

ArrType arr = {1, 2, 3, 4, 5, 6}; ArrType* pArr;

// Same as: // char arr = {1, 2, 3, 4, 5, 6}; // char (*pArr);

Here, is the new alias for the type, which is an array type with 6 elements. For , is a pointer pointing to the memory of the type.

Type casts A typedef is created using type definition syntax but can be used as if it were created using type cast syntax. (Type casting changes a data type.) For instance, in each line after the first line of:

// `FuncPtr` is a pointer to a function which takes a `double` and returns an `int`. typedef int (*FuncPtr)(double);

// Valid in both C and C++. FuncPtr x = (FuncPtr)nullptr;

// Only valid in C++. FuncPtr y = FuncPtr(nullptr); FuncPtr z = static_cast<FuncPtr>(nullptr);

is used on the left-hand side to declare a variable and is used on the right-hand side to cast a value. Thus, the typedef can be used by programmers who do not wish to figure out how to convert definition syntax to type cast syntax.

Without the typedef, it is generally not possible to use definition syntax and cast syntax interchangeably. For example:

void* p = nullptr;

// This is legal. int (*x)(double) = (int (*)(double)) p;

// Left-hand side is not legal. int (*)(double) y = (int (*)(double)) p;

// Right-hand side is not legal. int (*z)(double) = (int (*p)(double));

Usage in C++ In C++ type names can be complex especially with namespace clutter, and typedef provides a mechanism to assign a simple name to the type.

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;

// ... }

and

typedef std::pair<std::string, int> Value; typedef std::vector<Value> Values;

Values values;

for (Values::const_iterator i = values.begin(); i != values.end(); ++i) { Value const& t = *i;

// ... }

C++11 introduced the possibility to express typedefs with instead of . For example, the above two typedefs could equivalently be written as

using Value = std::pair<std::string, int>; using Values = std::vector<Value>;

Use with templates C++03 does not provide templated typedefs. For instance, to have represent for every type one cannot use:

template <typename T> typedef std::pair<std::string, T> StringPair<T>; // Doesn't work