Benutzer:Llf-tec/typedef
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
Indizierung was eine Variable repräsentiert
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
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
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
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
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++
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
}
Use with C++ templates
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
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 Int
s.
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
References
Vorlage:Reflist [[Category:C programming language]] [[Category:C++]] [[Category:Articles with example C code]] [[Category:Articles with example C++ code]]
- ↑ Typedef als ein Synonym. Es erlaubt dir Synonyme für Typen ein zu führen, welche in anderer weiße deklaiert wurden.
- ↑ 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.“
- ↑ http://msdn.microsoft.com/en-us/library/aa664765(VS.71).aspx