2013-02-18 25 views
8

Sono nuovo nel kernel di Linux. Sto leggendo il file ioctl.h, ci ho incontrato una macro _IOC_TYPECHECK(t), che assomiglia a questo:Che cosa significa sizeof (int [1])?

#define _IOC_TYPECHECK(t) \ 
     ((sizeof(t) == sizeof(t[1]) && \ 
      sizeof(t) < (1 << _IOC_SIZEBITS)) ? \ 
      sizeof(t) : __invalid_size_argument_for_IOC) 

Mi potete spiegare questo codice? In questo codice, cosa significa sizeof(t[1])?

risposta

7

Viene utilizzato per verificare la validità del terzo parametro sui macro _IOR/_IOW/_IOWR, che si suppone essere un tipo. Controlla che il parametro sia in realtà un tipo (e non una variabile o un numero) e causa altrimenti un errore del compilatore o del linker.

  • Se t è un tipo, quindi t[1] è del tipo "un array di 1 t". Questo tipo ha le stesse dimensioni di t e pertanto sizeof(t) == sizeof(t[1]) è vero.

  • Se t è un numero, sizeof(t) non verrà compilato.

  • Se t è una variabile semplice (non array), quindi t[1] causerà un errore del compilatore.

  • Se t è una variabile di matrice, sizeof(t) == sizeof(t[1]) sarà falso, e sarà provocato un errore di linker (perché __invalid_size_argument_for_IOC non è definito).

L'espressione sizeof(t) < (1 << _IOC_SIZEBITS) controlla che la dimensione del tipo t non supera il massimo consentito per ioctl, e provoca lo stesso errore linker altrimenti.

Ci sono ancora alcuni casi non validi che non verranno catturati da questa macro - ad esempio, quando t è un puntatore a un puntatore.

+0

"Se' t' è una variabile di matrice, 'sizeof (t) == sizeof (t [1])' sarà false "è davvero vero? –

+0

@AndreasGrapentin: non per un array di un elemento, ma è possibile che venga visualizzato un avviso del compilatore per indicizzare l'array fuori limite. – interjay

3

Significa lo stesso di tutti gli altri usi di sizeof. Calcola la dimensione dell'espressione.

In questo caso particolare, ho il sospetto che il controllo abbia lo scopo di garantire alcune proprietà di t (che dovrebbe essere un nome di tipo, non una variabile) che non conosco dal contesto ... Forse è possibile trattarlo come un puntatore (necessario per l'indicizzazione dell'array) che escluderebbe alcuni tipi. Il commento accanto alla macro dice /* provoke compile error for invalid uses of size argument */ che sembra supportare questa teoria.

Si noti che sizeof è un operatore, non una funzione. Le parentesi non sono necessarie, tranne quando si desidera calcolare direttamente le dimensioni di un tipo e quindi fanno parte dell'espressione (è un'espressione cast). Quindi questo potrebbe essere scritto sizeof t == sizeof t[1] && ..., o forse (sizeof t == sizeof t[1]) per chiarezza.

Questo è uno stile molto buono da utilizzare, poiché "blocca" la dimensione da calcolare alla matrice corretta, invece di ripetere il tipo di t. Quindi, se il tipo dovesse cambiare, l'espressione si adatterebbe automaticamente e calcolerebbe ancora la cosa giusta.

Molti programmatori C sembrano preferire la parentesi intorno all'argomento a sizeof in tutti i casi, per qualche motivo.

+1

't' qui dovrebbe essere un tipo, non una variabile. È il terzo parametro per le macro [_IOR] (http://h30097.www3.hp.com/docs/dev_doc/DOCUMENTATION/HTML/DDK_R2/DOCS/HTML/MAN/MAN9/0028___H.HTM)/_IOW/_IOWR. – interjay

+0

Non sapevo che i parametri di 'sizeof' erano facoltativi tranne per un tipo; o che sono tecnicamente un cast in quel caso. +1 solo per quello! – Chowlett

+1

"e quindi fanno parte dell'espressione". Non sono sicuro di capire cosa intendi qui. Un identificatore di tipo (come 'int') non ha bisogno di avere parentesi e non è un'espressione ma le parentesi sono obbligatorie in' sizeof (int) 'perché queste sono le regole grammaticali ... o si stava ottenendo qualcosa di diverso? Inoltre, questo non è un cast neanche. –