C Typedef e Struct Question

Qual è la differenza tra queste due dichiarazioni, ed è una preferita rispetto all’altra?

typedef struct IOPORT { GPIO_TypeDef* port; u16 pin; } IOPORT; typedef struct { GPIO_TypeDef* port; u16 pin; } IOPORT; 

Per quanto riguarda lo stile preferito, preferisco il 1o stile (con il nome sia nel tag struct sia come typedef per la struct) semplicemente perché non ci sono altri svantaggi oltre a qualche altro carattere nel file sorgente. Lo struct snippet del mio IDE cancella il nome in entrambe le posizioni, quindi ottengo sempre un nome struct typedef’ed insieme a un nome di tag struct.

Ottieni alcuni piccoli vantaggi:

  • la ” struct STRUCTNAME ” può essere usata per dichiarare i puntatori alla struct all’interno della struct
  • puoi farcela usando solo STRUCTNAME in codice C o C ++
  • si evita una stranezza potenziale (anche se molto rara nella pratica) in C ++ che ha a che fare con il nome della struct usato per un altro object senza errori o avvertimenti

Ma se mi capita di digitare manualmente la definizione della struct, spesso trascurerò pigramente dichiarando uno o l’altro nome.

il primo consente di utilizzare IOPORT all’interno della struttura per fare riferimento a oggetti dello stesso tipo. utile in casi come le liste collegate in cui un nodo deve fare riferimento a un nodo.

C ha quattro diversi spazi dei nomi, in cui lo spazio dei nomi dei tag della struttura è uno di essi. Quindi:

 struct foo { int bar; }; 

non definisce un nuovo tipo in senso generale. Quando hai solo un tag di struttura, devi anteporre la parola chiave ‘struct’ in dichiarazioni di oggetti come questa:

 foo b; /* error */ struct foo b; /* correct */ 

Inoltre, puoi immediatamente istanziare un nuovo object nella definizione come questa:

 struct foo { int bar; } baz; 

Dove baz è un object di tipo struttura foo. Tuttavia, spesso si vuole definire una struttura come un nuovo tipo, per risparmiare un po ‘di scrittura. Un tipo completo non fa riferimento ai tag di struttura, quindi puoi omettere il prefisso ‘struct’ durante le dichiarazioni.

 typedef struct foo { int bar; } baz; 

Permette comunque di dichiarare oggetti con ‘struct foo’, dato che foo è il tag struct. Ma ora è promosso a un tipo completo nello spazio dei nomi di tipo “normale”, in cui è noto come tipo baz. Quindi con un typedef, i campi “baz” hanno una semantica diversa.

A meno che non sia necessario dichiarare puntatori al tipo di struttura all’interno di se stesso (liste collegate, strutture ad albero), ometterlo. L’aggiunta di uno che non è richiesto inquina solo lo spazio dei nomi.

Il primo esempio ti permette di usare l’object dentro se stesso per cose che si trovano elenchi e alberi collegati (come sottolinea Victor ). Il secondo è un esempio di tipi anonimi che l’esperienza ha insegnato a non comportarsi bene con tutti i compilatori. Quindi il primo approccio è probabilmente raccomandato. Se non ti interessa che la struttura sia in grado di fare riferimento a se stessa, puoi sempre dargli un nome che è improbabile che sia in conflitto come __SOMEPREFIX_IOPORT__ per esempio.