typedef ist ein Schlüsselwort in den Programmiersprachen C++ und C. Der Zweck von typedef ist Klassen oder anderen Schlüsselwörten neue Namen zu geben. Diese Variablen haben oft umständliche oder verwirrende Namen.[1]

In der C-Konvention (wie in der Standard C Library) wurde bestimmt, dass Typen, die mit typedef deklariert wurden, mit '_t' enden (z.B., size t, time t).

Verwendungsbeispiele

Bearbeiten

Indizierung was eine Variable repräsentiert

Bearbeiten

Ein typedef kann zum Zeigen, wie eine Variable etwas representiert genutzt werden, z.B., Maßeinheit oder Zahl:

int current_speed;
int high_score;
...

void congratulate(int your_score) {
    if (your_score > high_score)
...

Jetzt betrachte das:

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)
...

Beide Beispiele des Codes tun das gleiche. Jedoch, die Benutzung von typedef im zweiten Beispiel macht es klar, dass die zwei Variablen, während sie den gleichen Datentype (int) representieren, verschieden und inkompatibl sind. Die Erklärung in congratulate() von your_score zeigt dem Programmierer an, dass current_speed (oder jede andere Variable, die nicht mit points deklaiert wurde) nicht als Argument übergeben werden sollte. Dies wäre nicht so deutlich, wenn beide als int deklaiert wären. Jedoch, beachte dass die Anzeige for the programmer only ist; Im unteren Codeschnippsel ist der C/C++ Kompiler der Auffassung das beide Variablen als int deklairt wurden, so mit wird er keine Warnungen oder Fehlermeldungen für congratulate(points your_score) ausgeben:

void foo() {
    km_per_hour km100 = 100;
    congratulate(km100);
...

Obwohl der Kompiler der Auffassung ist, dass im obrigen Code km_per_hour equivalent mit int ist. Die zwei Variablen sind nicht austauschbar, wenn der Type mit einem Prefix von unsigned, signed oder long getauscht ist.

void foo() {
    unsigned int a;         // Okay
    unsigned km_per_hour b; // Compiler complains
    long int c;             // Okay
    long km_per_hour d;     // Compiler complains
...

Vereinfachen einer Deklaration

Bearbeiten

Ein typedef kann genutzt werden um eine declaration zu vereinfachen:

struct MyStruct {
    int data1;
    char data2;
};

Hier (oben) wurde ein struct MyStruct Datentype definiert. Um eine Variable mit diesem Type zu deklaieren (unten) braucht man das struct-Schlüsswort (Man braucht es in C++ nicht.):

struct MyStruct a;

Ein typedef kann dafür benutzt werden, dass man das struct-Schlüsselwort (in C) weglassen kann. Zum Beispiel, mit:

typedef struct MyStruct newtype;

wir können jetzt eine Variable mit diesem Typen deklaieren:

newtype a;

Beachte das die structure- und typedef-Definition stattdessen auch in ein einziges Statement kombiniert werden kann:

typedef struct MyStruct {
    int data1;
    char data2;
} newtype;

Oder wir können es auch einfacher so nutzen:

typedef struct {
    int data1;
    char data2;
} newtype;

In C++, im unterschied zu C, das struct-, class-, und enum-Schlüsselwort sind nicht von nöten in Variablendeklarationen welche separat von den Definitionen sind:

struct MyStruct x;       // This is legal
MyStruct y;              // This is also legal

Als solch, MyStruct kann benutzt werden wo immer newtype benutzt werden kann. Jedoch ist es nicht das gleiche; zum Bespiel kann die Konstruktor-Methode von MyStruct nicht newtype heißen.

Typedef mit Pointer benutzen

Bearbeiten

Typedefs können auch Deklarationen für Pointer-Typen vereinfachen. Betrachten sie folgendes:

struct Node {
    int data;
    struct Node *nextptr;
};

In C kann man mehrfach Variablen des selben Typen in einem Statement deklaieren, auch gemischte Pointer und nicht Pointer. Jedoch muss man ein Sternchen an jede Variable voranstellen um es als Pointer zu signieren. In the following, a programmer might assume that errptr was indeed a Node *, but a typographical error means that errptr is a Node. Dies kann zu subtilen Syntax-Fehlern führen.

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

Wenn man ein Node * typedef definiert ist es sicher dass alle Variablen Pointer-Typen sein werden.

typedef struct Node *NodePtr;
...
NodePtr startptr, endptr, curptr, prevptr, errptr, refptr;

Typedef mit casts verwenden

Bearbeiten

A typedef is created using type declaration 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:

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

Usage concerns

Bearbeiten

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.

Usage in C++

Bearbeiten

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
}

There is no direct way to have templated typedefs in C++. For instance, to have stringpair<T> represent std::pair<std::string, T> for every type T 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 of stringpair<T> then it is possible to achieve the desired result via a typedef within an otherwise unused templated class 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;
};

Other languages

Bearbeiten

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 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.[3]

using newType = global::System.Runtime.Interop.Marshal;
using otherType = Enums.MyEnumType;
using StringListMap = System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<string>>;

See also

Bearbeiten

References

Bearbeiten

Vorlage:Reflist [[Category:C programming language]] [[Category:C++]] [[Category:Articles with example C code]] [[Category:Articles with example C++ code]]

  1. Typedef als ein Synonym. Es erlaubt dir Synonyme für Typen ein zu führen, welche in anderer weiße deklaiert wurden.
  2. Kroah-Hartman, Greg: Proper Linux Kernel Coding Style. In: Linux Journal. 1. Juli 2002, abgerufen am 23. September 2007: „Using a typedef only hides the real type of a variable.“
  3. http://msdn.microsoft.com/en-us/library/aa664765(VS.71).aspx