Typedeftypedef 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,[1] except in the obscure case of a qualified typedef of an array type where the typedef qualifiers are transferred to the array element type.[2] 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.[1] SyntaxA typedef declaration follows the same syntax as declaring any other C identifier. The keyword In the C standard library and in POSIX specifications, the identifier for the typedef definition is often suffixed with Examples
This creates the type typedef int length;
Documentation useA typedef declaration may be used as documentation by indicating the meaning of a variable within the programming context, e.g., it may include the expression of a unit of measurement or counts. The generic declarations, int current_speed;
int high_score;
void congratulate(int your_score) {
if (your_score > high_score) {
// ...
}
}
may be expressed by declaring context specific types: typedef int km_per_hour;
typedef int points;
// `km_per_hour` is synonymous with `int` here, and thus, the compiler treats
// our new variables as integers.
km_per_hour current_speed;
points high_score;
void congratulate(points your_score) {
if (your_score > high_score) {
// ...
}
}
Both sections of code execute identically. However, the use of typedef declarations in the second code block makes it clear that the two variables, while representing the same data type void foo() {
km_per_hour km100 = 100;
congratulate(km100);
}
Declaration simplificationA typedef may be used to simplify the declarations of objects having types with verbose names, such as struct, union, or pointer types.[5] For example, struct MyStruct {
int data1;
char data2;
};
defines the data type struct MyStruct a;
A typedef declaration can provide a simpler type name that does not include typedef struct MyStruct newtype;
the variable declaration can be reduced to: newtype a;
The structure declaration and typedef may also be combined into a single declaration: typedef struct MyStruct {
int data1;
char data2;
} newtype;
, including when no tag is declared: typedef struct {
int data1;
char data2;
} newtype;
In C++, unlike in C, tags of struct MyStruct x;
MyStruct y;
Indeed, for 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, A notorious example where even C++ needs the int stat(const char *filename, struct stat *buf)
{
// ...
}
Here both C as well as C++ need the PointersThe typedef may be used to define a new pointer type. typedef int *intptr;
intptr ptr;
// Same as:
// int *ptr;
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, Constant pointersAgain, 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 = NULL;
// Same as:
// int *const ptr = NULL;
Since it is a constant pointer, it must be initialized in the declaration. Structures and structure pointersTypedefs can also simplify definitions or declarations for structure pointer types. Consider this: struct Node {
int data;
struct Node *nextptr;
};
Using typedef, the above code can be rewritten like this: typedef struct Node Node;
struct Node {
int data;
Node *nextptr;
};
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 struct Node *startptr, *endptr, *curptr, *prevptr, errptr, *refptr;
By defining the typedef typedef struct Node* NodePtr;
NodePtr startptr, endptr, curptr, prevptr, errptr, refptr;
Function pointersint 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, 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 is cryptic as it does not clearly show what the function accepts as arguments, or the type that it returns. A novice programmer may even assume that the function accepts a single typedef void (*sighandler_t)(int);
sighandler_t signal(int sig, sighandler_t func);
ArraysA typedef can also be used to simplify the definition of array types. For example, typedef char arrType[6];
arrType arr = {1, 2, 3, 4, 5, 6};
arrType *pArr;
// Same as:
// char arr[6] = {1, 2, 3, 4, 5, 6};
// char (*pArr)[6];
Here, Type castsA 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) NULL;
// Only valid in C++.
funcptr y = funcptr(NULL);
funcptr z = static_cast<funcptr>(NULL);
Without the typedef, it is generally not possible to use definition syntax and cast syntax interchangeably. For example: void *p = NULL;
// 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, 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_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;
// ...
}
C++11 introduced the possibility to express typedefs with using value_t = std::pair<std::string, int>;
using values_t = std::vector<value_t>;
Use with templatesC++03 does not provide templated typedefs. For instance, to have template<typename T>
typedef std::pair<std::string, T> stringpair<T>; // Doesn't work
However, if one is willing to accept template<typename T>
class stringpair
{
private:
// Prevent instantiation of `stringpair<T>`.
stringpair();
public:
// Make `stringpair<T>::type` represent `std::pair<std::string, T>`.
typedef std::pair<std::string, T> type;
};
// Declare a variable of type `std::pair<std::string, int>`.
stringpair<int>::type my_pair_of_string_and_int;
In C++11, templated typedefs are added with the following syntax, which requires the template <typename T>
using stringpair = std::pair<std::string, T>;
// Declare a variable of type `std::pair<std::string, int>`.
stringpair<int> my_pair_of_string_and_int;
Other languagesIn SystemVerilog, typedef behaves exactly the way it does in C and C++.[7] In many statically typed functional languages, like Haskell, Miranda, OCaml, etc., one 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 In Seed7 the definition of a constant type is used to introduce a synonym for a type: const type: myVector is array integer; In Swift, one uses the typealias PairOfInts = (Int, Int)
C# contains a feature which is similar to the typedef or the using newType = global::System.Runtime.Interop.Marshal;
using otherType = Enums.MyEnumType;
using StringListMap = System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<string>>;
In D the keyword struct Foo(T){}
alias FooInt = Foo!int;
alias Fun = int delegate(int);
Usage concernsKernighan and Ritchie stated two reasons for using a typedef.[1] First, it provides a means to make a program more portable or easier to maintain. Instead of having to change a type in every appearance throughout the program's source files, only a single typedef statement needs to be changed. Some programmers 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.[10] See alsoReferences
|