2013-02-18 8 views
8

Ich bin neu im Linux-Kernel. Ich lese die Datei ioctl.h, dort traf ich ein Makro _IOC_TYPECHECK(t), die wie folgt aussieht:Was bedeutet sizeof (int [1])?

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

Können Sie mir diesen Code erklären? Was bedeutet in diesem Code sizeof(t[1])?

Antwort

7

Dies wird verwendet, um die Gültigkeit des dritten Parameters zu den _IOR//_IOWR Makros, die ein Typ sein soll, zu überprüfen. Es überprüft, dass der Parameter tatsächlich ein Typ (und keine Variable oder eine Zahl) ist und andernfalls einen Compiler- oder Linkerfehler verursacht.

  • Wenn t ist ein Typ, dann ist der Typ t[1] "eine Anordnung von 1 t". Dieser Typ hat die gleiche Größe wie t, und daher ist wahr.

  • Wenn t eine Zahl ist, kann sizeof(t) nicht kompiliert werden.

  • Wenn t eine einfache (Nicht-Array-) Variable ist, verursacht t[1] einen Compilerfehler.

  • t Wenn ein Array Variable ist, wird sizeof(t) == sizeof(t[1]) falsch sein, und ein Linker-Fehler verursacht werden (weil __invalid_size_argument_for_IOC nicht definiert ist).

Der Ausdruck sizeof(t) < (1 << _IOC_SIZEBITS) überprüft, dass die Größe des Typs t nicht das Maximum für ioctl erlaubt nicht überschreitet und bewirkt, daß die sonst gleichen Linker Fehler.

Es gibt noch einige ungültige Fälle, die von diesem Makro nicht abgefangen werden - zum Beispiel, wenn t ein Zeiger auf einen Zeiger ist.

+0

"Wenn' t' eine Arrayvariable ist, wird 'sizeof (t) == sizeof (t [1])' falsch sein "ist das wirklich immer wahr? –

+0

@AndreasGrapentin: Nicht für ein Array von einem Element, aber dann erhalten Sie möglicherweise eine Compiler-Warnung für die Indizierung des Arrays außerhalb der Grenzen. – interjay

3

Es bedeutet das gleiche wie alle anderen Anwendungen von sizeof. Er berechnet die Größe des Ausdrucks.

In diesem speziellen Fall vermute ich, dass die Überprüfung eine Eigenschaft von t (die ein Typname sein sollte, keine Variable), die ich nicht aus dem Kontext weiß ... Vielleicht ist das möglich um es als Zeiger zu behandeln (benötigt für die Array-Indizierung), der einige Typen ausschließen würde. Der Kommentar neben dem Makro sagt /* provoke compile error for invalid uses of size argument */, die diese Theorie zu unterstützen scheint.

Beachten Sie, dass sizeof ein Operator ist, keine Funktion. Die Klammern werden nicht benötigt, es sei denn, Sie möchten die Größe eines Typs direkt berechnen und sind dann Teil des Ausdrucks (es handelt sich um einen Cast-Ausdruck). So könnte dies sizeof t == sizeof t[1] && ... oder vielleicht (sizeof t == sizeof t[1]) für die Klarheit geschrieben werden.

Dies ist ein sehr guter Stil zu verwenden, da es die Größe, die auf das richtige Array berechnet wird, "sperrt", anstatt den Typ t zu wiederholen. Wenn sich der Typ also ändert, passt sich der Ausdruck automatisch an und berechnet immer noch das Richtige.

Viele C-Programmierer scheinen in allen Fällen aus irgendeinem Grund Klammern um das Argument zu sizeof zu haben.

+1

't' hier soll ein Typ sein, keine Variable. Es ist der dritte Parameter für die Makros [_IOR] (http://h30097.www3.hp.com/docs/dev_doc/DOCUMENTATION/HTML/DDK_R2/DOCS/HTML/MAN/MAN9/0028___R.HTM)/_IOW/_IOWR. – interjay

+0

Ich wusste nicht, dass 'sizeof's Parameter optional waren, außer für einen Typ; oder dass sie in diesem Fall technisch gesehen eine Besetzung sind. +1 nur dafür! – Chowlett

+1

"und dann sind sie Teil des Ausdrucks". Ich bin mir nicht sicher, ob ich verstehe, was du hier meinst. Ein Typbezeichner (wie 'int') muss keine Klammern haben und ist kein Ausdruck, aber die Klammern sind in' sizeof (int) 'erforderlich, weil das die Grammatikregeln sind ... oder hast du etwas anderes gefunden? Auch das ist keine Besetzung. –