2015-08-07 15 views
6

Questa domanda nasce dalla domanda Is a struct {...}; a type or an unnamed variable?Legalità del `typedef struct foo {int bar};`

In questa domanda, il PO ha chiesto circa

typedef struct student_s { 
    char* name; 
    int age; 
    double height; 
    struct student_s* next; 
}; 

sto chiedendo circa la legittimità di quanto sopra . È necessaria una diagnostica quando il codice che contiene quanto sopra è compilato (o per semplificare, typedef struct foo {int bar;};)?

La mia opinione è che è legale, che non è richiesta una diagnosi dal punto di vista di un avvocato linguistico. (A parte: non sto sostenendo di utilizzare questo è molto degno di una diagnosi Mi piacerebbe molto desidera che il compilatore di avvertirmi se ho erroneamente scritto il codice come sopra...)


Sezione 6.7 dello standard C11 detta la sintassi di una dichiarazione: dichiarazione-identificatori init-declarator-list opt; Si noti che la lista di avvio-dichiarazione è facoltativa. Ciò potrebbe indurre a pensare che typedef int; sia valido. Non è perché lo standard dice anche che

Una dichiarazione diversa da una dichiarazione static_assert deve dichiarare almeno un dichiaratore (diverso dai parametri di una funzione o dei membri di una struttura o unione), un tag, o i membri di un'enumerazione.

Così typedef int; e typedef struct {int bar}; sono illegali perché non dichiarano un dichiaratore, un tag, o un membro di un'enumerazione.

D'altra parte, mi sembra che typedef struct foo {int bar;}; sia legale perché dichiara qualcosa. In particolare, dichiara e definisce il tag structfoo.

Il ragionamento sopra è corretto?

+0

Penso che dichiara '{int bar; } ', non puoi fare nulla di utile con esso. – this

+0

@David Hammen Non c'è un dichiaratore in questo typedef. –

+0

@questo: lo standard (vedere la mia citazione nella domanda) esclude specificamente i membri di una struttura o unione. Quindi 'typedef struct {int bar;};' è illegale. –

risposta

1

6.7.1 specificatori Classe di stoccaggio definisce typedef come un identificatore di classe di archiviazione con il seguente commento: L'identificatore typedef si chiama ‘‘classe di archiviazione specificatore’’ per convenienza sintattica solo;

E 6.7 Dichiarazione contiene:

Sintassi:

  • dichiarazione:
    • dichiarazione-committenti init-dichiaratore-list opt
  • dichiarazione-prescrittori:
    • stoccaggio -class-specificatore-dichiarazione-s pecifiers opt
    • tipo specificatore dichiarazione-specificatori opt
    • tipo-qualificazione dichiarazione-specificatori opt
    • funzione-specificatore dichiarazione-specificatori opt
  • init-declarator- lista:
    • init-dichiarator
    • init-dichiaratore-list, init-dichiaratore
  • init-dichiaratore:
    • dichiaratore
    • dichiaratore = inizializzazione

Prima vincolo è: Una dichiarazione deve dichiarare almeno un dichiaratore (diversi dai parametri di una funzione o i membri di una struttura o unione), un tag, o membri di un'enumerazione

Come init-dichiaratore-lista è facoltativo in una dichiarazione, ha fornito un dichiaratore o tag è dichiarato, direi che typedef struct foo {int bar;}; è una dichiarazione scomposta come storage-class-specifier type-specifier senza inizializzatore. Tuttavia, poiché lo specificatore del tipo dichiara internamente un tag (foo), il vincolo viene rispettato.

La mia conclusione è che un tale costrutto è valido e produce solo avvertimenti sui compilatori.

+0

Non c'è un dichiaratore. foo è un tag di struttura. –

+0

@VladfromMoscow Grazie per l'osservazione. Post modificato. –

+0

@David Hammen E ho scritto questo nella mia risposta. –

2

Nella citazione citata c'è scritto che una dichiarazione deve dichiarare tra l'altro un tag.

Quindi questa dichiarazione

typedef struct student_s { 
    char* name; 
    int age; 
    double height; 
    struct student_s* next; 
}; 

dichiara semplicemente struct student_s ed equivalente alla dichiarazione, senza l'identificatore typedef

struct student_s { 
    char* name; 
    int age; 
    double height; 
    struct student_s* next; 
}; 

Lo fa non introduce un nome typedef nel campo di applicazione.

+0

Capisco cosa fa questo codice, che non introduce un nome typedef. Questo non risponde alla domanda. Non riuscire a introdurre un nome typedef di per sé può essere considerato una violazione di una regola o vincolo di sintassi e, di conseguenza, deve comportare una diagnostica (5.1.1.3 Diagnostica). –

+0

@David Hammen Cosa? !!! Ho dimostrato che è una dichiarazione corretta. Qual è il problema con te? –

+0

Vlad, scusa, non ho letto la tua risposta in questo modo. Dopo aver riletto, vedo che è esattamente quello che stai dicendo. –

0

questo typedef:

typedef struct student_s { 
    char* name; 
    int age; 
    double height; 
    struct student_s* next; 
}; 

ottengono i seguenti:

warning useless storage class specifier in empty declaration [enabled by default] 

Così la sintassi è accettabile, ma senza un dichiarante, il codice è trash