Typedef

De la Wikipedia, enciclopedia liberă.
Salt la navigare Salt la căutare

typedef este un cuvânt cheie al limbajelor de programare C și C ++ . Scopul typedef este de a atribui nume alternative tipurilor de date existente, de obicei acelea a căror declarație standard este prea greoaie, poate confuză, sau de a face codul mai ușor reutilizabil între o implementare și alta.

Conform convențiilor C (bibliotecă standard), tipurile declarate cu typedef încheie cu șirul „_t” (de exemplu, size_t , time_t ).

Exemple de utilizare

Pentru a indica ce reprezintă o variabilă

Un typedef poate fi folosit pentru a indica modul în care o variabilă reprezintă ceva, cum ar fi o unitate de măsură:

 int current_speed ;
int high_score ;
...

void felicit (your_score int) {
    if ( scorul tău > scor înalt )
...

Acum ia în considerare:

 typedef int km_per_hour ;
puncte int typedef ;

km_per_hour current_speed ;
puncte high_score ;
...

nul felicită ( punctează scorul dvs. ) {
    if ( scorul tău > scor înalt )
...

Ambele secțiuni de cod implementează aceeași operație. Cu toate acestea, utilizarea typedef în al doilea exemplu clarifică faptul că, deși cele două variabile sunt reprezentate de același tip de date ( int ), informațiile pe care le conțin sunt logic incompatibile. Declarația „ congratulate() a your_score îi spune programatorului că current_speed (sau orice altă variabilă nedeclarată ca points ) nu trebuie transmisă ca argument. Acest lucru nu ar fi fost atât de vizibil dacă ambele ar fi declarate ca numere întregi. Rețineți că indicația este utilă doar pentru programatori; Compilatorul C / C ++ tratează ambele variabile ca un întreg și nu va raporta nicio inconsecvență dacă treceți current_speed ca argument la funcția congratulate() .

Simplificați o afirmație

Un typedef poate fi utilizat pentru a simplifica declarația unui tip de date compozit ( struct , union ) sau a unui pointer .

 struct var {
    int data1 ;
    int data2 ;
    char data3 ;
};

Deasupra tipului de date struct var a fost definit. Pentru a declara o variabilă de acest tip, în C, este necesară utilizarea cuvântului cheie struct (acest lucru nu se aplică C ++):

 struct var a ;

Un typedef poate fi folosit pentru a elimina necesitatea de a repeta cuvântul struct . De exemplu cu:

 typedef struct var nou tip ;

acum putem crea o variabilă de acest tip cu:

 nou tip pentru ;

Rețineți că definiția structurii și typedef pot fi combinate într-o singură declarație:

 typedef struct var {
    int data1 ;
    int data2 ;
    char data3 ;
} tip nou ;

În C ++ , spre deosebire de C, cuvintele cheie struct , class și enum sunt opționale în declarațiile variabile care sunt separate de definiții.

 struct var x ; // Acest lucru este permis
var y ; // Acest lucru este, de asemenea, permis

Astfel, var poate fi folosit ori de câte ori newtype poate fi utilizat. Cu toate acestea, inversul nu este adevărat. De exemplu, metoda constructorului pentru var nu poate fi numită tip newtype .

Folosiți typedef cu indicii

Typedefs pot simplifica, de asemenea, declarațiile pentru tipurile de pointer. Gandeste-te la asta:

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

În C, este posibil să declarați mai multe variabile de același tip într-o singură declarație, chiar și prin amestecarea de indicatori și non-indicatori. Oricum ar fi, trebuie să puneți un asterisc în fața fiecărei variabile pentru a face un pointer.

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

Un programator probabil ar presupune că errptr fost de fapt de tipul Node * , dar pentru o greșeală de tip errptr este de tip Node . Acest lucru va duce la o eroare de sintaxă.

Prin definirea unui typedef pentru Node * , sunteți sigur că toate variabilele vor fi de tip pointer.

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

Utilizați tipul de tip turnat

Un typedef este creat folosind sintaxa declarației de tip, dar poate fi folosit ca și cum ar fi creat folosind sintaxa tip cast . De exemplu, în fiecare linie de cod după prima linie a:

 typedef int ( * funcptr ) ( dublu ); // pointer pentru a funcționa cu argument dublu și returnează tip int
funcptr x = ( funcptr ) NULL ; // C sau C ++
funcptr y = funcptr ( NULL ); // C sau C ++
funcptr z = static_cast <funcptr> (NULL); // numai C ++

funcptr este utilizat în partea stângă pentru a declara o variabilă și în partea dreaptă a atribuirii pentru a converti o valoare. Astfel, tipurile pot fi utilizate de programatorii care nu doresc să înțeleagă cum să convertească sintaxa declarativă în sintaxă de exprimare.

Rețineți că, fără typedefs, în general nu este posibilă utilizarea sintaxei declarative și exprimate în mod interschimbabil. De exemplu:

 int ( * x ) ( double ) = ( int ( * ) ( double )) NULL ; // Acest lucru este permis
int ( * ) ( dublu ) y = ( int ( * ) ( dublu )) NULL ; // Partea stângă a sarcinii nu este eligibilă
int ( * z ) ( double ) = ( int ( * NULL ) ( double )); // Partea dreaptă a sarcinii nu este eligibilă

Îngrijorări legate de utilizare

Unii se opun utilizării intensive a typedefs. Motivul principal este faptul că typedefs ascund adevăratul tip de date al variabilei. De exemplu, Greg Kroah-Hartman , un hacker experimentat și dezvoltator al kernel-ului Linux , descurajează utilizarea lor pentru orice altceva decât o declarație de prototip de funcție. El susține că această practică nu numai că ofensează inutil codul, dar poate provoca confuzie și în programatorul care folosește accidental structuri mari de date, crezând că sunt elementare. [1]

Alții susțin că utilizarea typedefs facilitează revizuirea codului. K&R afirmă că există două motive pentru utilizarea typedefs. În primul rând, fac codul mai portabil. În loc să trebuiască să schimbați un tip de date de fiecare dată când apare în întreaga sursă, se modifică doar un singur tip. În al doilea rând, tipurile pot face o declarație complexă mai ușor de înțeles.

Folosiți în C ++

În C ++, numele tipurilor pot fi foarte complicate, iar typedef oferă un mecanism pentru atribuirea unui nume simplu tipului.

 std :: vector <std :: pair <std :: string, int >> valori;
for ( std :: vector < std :: pair < std :: string , int >> :: const_iterator i = valori . begin (); i ! = valori . end (); ++ i )
{
   std :: pair < std :: string , int > const & t = * i ;
   // Fă ceva
}

Și

 typedef std :: pair < std :: string , int > value_t ;
typedef std :: vector < valoare_t > valori_t ;

valori_t valori ;
for ( valori_t :: const_iterator i = valori . begin (); i ! = valori . end (); ++ i )
{
   valoare_t const & t = * i ;
   // Fă ceva
}

Se folosește cu șabloane în C ++

Nu există o modalitate directă de a avea un typedef într-un șablon C ++. De exemplu, pentru a face value_t<T> reprezintă std::pair<std::string, T> pentru orice class T pe care nu se poate utiliza:

 șablon < clasa T >
typedef std :: pair < std :: string , T > value_t < T > ; // Nu funcționează

Cu toate acestea, dacă doriți să acceptați value_t<T>::foo , sau ceva similar, în loc de value_t<T> , atunci puteți obține rezultatul dorit cu un typedef într-o clasă sau structură conținută într-un șablon:

 șablon < clasa T >
struct valoare_t
{
    typedef std :: pair < std :: string , T > foo ; // Face valoare_t <T> :: foo reprezintă std :: pair <std :: string, T>
};

Din C ++ 11 este posibil să utilizați o declarație alias folosind cuvântul cheie using pentru a obține rezultatul dorit:

 șablon < typename T >
folosind TaggedValue = std :: pair < std :: string , T > ; // legal din C ++ 11

void foo (TaggedValue <int> foo);

Alte limbi

Într-o varietate de limbaje funcționale de programare , cum ar fi ' Haskell , Miranda , OCaml etc., este posibil să se definească așa-numitele sinonime de tip, sinonime de tip, care corespund tipului de tip din C. Un exemplu scris în Haskell:

 tip PairOfInts = (Int, Int)

Acest exemplu definește un sinonim tip numit „PairOfInts” care are aceeași semnificație ca o pereche de numere întregi.

C # include o caracteristică similară cu C typedef, dar dezavantajul este că trebuie declarat pentru fiecare fișier separat. [2]

 folosind newType = global :: System.Runtime.Interop.Marshal;
folosind otherType = Enums.MyEnumType;

Notă

  1. ^ Kroah-Hartman, Greg, Proper Linux Kernel Coding Style , pe linuxjournal.com , 07/01/2002. Adus 23-09-2007 .
  2. ^ [1] Articol MSDN despre typedef în C #

Elemente conexe