Warum bedeutet sizeof(my_arr)[0] compilieren und gleich sizeof(my_arr[0])?

Lesezeit: 3 Minuten

Benutzeravatar von bgomberg
bgomberg

Warum wird dieser Code kompiliert?

_Static uint32_t my_arr[2];
_Static_assert(sizeof(my_arr) == 8, "");
_Static_assert(sizeof(my_arr[0]) == 4, "");
_Static_assert(sizeof(my_arr)[0] == 4, "");

Die ersten beiden Behauptungen sind offensichtlich korrekt, aber ich hätte erwartet, dass die letzte Zeile fehlschlägt, da ich das so verstehe sizeof() sollte zu einem Integer-Literal ausgewertet werden, das nicht als Array behandelt werden kann. Mit anderen Worten, es würde genauso fehlschlagen wie die folgende Zeile:

_Static_assert(4[0] == 4, "");

Interessanterweise kann das Folgende tatsächlich nicht kompiliert werden (was dasselbe tun sollte, oder?):

_Static_assert(*sizeof(my_arr) == 4, "");

Fehler: ungültiges Typargument von unärem ‘*’ (hat ‘long unsigned int’) _Static_assert(*sizeof(my_arr) == 4, “”);

Wenn es darauf ankommt, verwende ich gcc 5.3.0

  • Ich vermute ( sizeof( my_arr ) )[ 0 ] scheitert.

    – Andreas Henle

    9. Oktober 2017 um 19:17 Uhr


  • Ein aktuelles Duplikat hat eine andere Variation dieser Syntax-Überraschung: Warum kompiliert sizeof(x)++?

    – Peter Cordes

    8. Mai 2020 um 2:34 Uhr

Benutzeravatar von Melpomene
Melpomene

sizeof ist keine Funktion. Es ist ein unärer Operator wie ! oder ~.

sizeof(my_arr)[0] analysiert als sizeof (my_arr)[0]was gerecht ist sizeof my_arr[0] mit überflüssigen Klammern.

Das ist einfach so !(my_arr)[0] analysiert als !(my_arr[0]).

Im Allgemeinen haben Postfix-Operatoren in C eine höhere Priorität als Präfix-Operatoren. sizeof *a[i]++ analysiert als sizeof (*((a[i])++)) (die Postfix-Operatoren [] und ++ angewendet werden a zuerst, dann die Präfixoperatoren * und sizeof).

(Dies ist die Ausdrucksversion von sizeof. Es gibt auch eine Typversion, die einen Typnamen in Klammern annimmt: sizeof (TYPE). In diesem Fall wären die Eltern erforderlich und Teil der sizeof Syntax.)

  • Ich wusste definitiv, dass sizeof ein unärer Operator und keine Funktion ist, aber ich habe es total vergessen. Hoppla. Danke für die ausführliche Erklärung. Die Tatsache, dass [] hat eine höhere Priorität als *, ist trotzdem interessant.

    – bgomberg

    9. Oktober 2017 um 20:41 Uhr

  • @melpomene Interessant. Ich habe nie daran gedacht sizeof ein unärer Operator sein.

    – Mutantentastatur

    10. Oktober 2017 um 14:03 Uhr

  • Meinst du nicht "... parses as sizeof (my_arr[0])"? Das Hinzufügen eines Leerzeichens ändert nicht wirklich etwas.

    – Bernhard Barker

    11. Oktober 2017 um 2:37 Uhr

  • ich würde empfehlen sizeof((my_array)[0]) stattdessen

    – Bolov

    14. Oktober 2017 um 13:59 Uhr

  • Warum wird sizeof als Operator betrachtet?

    – phuklv

    23. September 2018 um 13:17 Uhr

AnT steht mit Russlands Benutzer-Avatar
AnT steht zu Russland

sizeof hat zwei “Versionen”: sizeof(type name) und sizeof expression. Ersteres erfordert ein Paar () um seine Argumentation. Aber letzteres – das mit einem Ausdruck als Argument – hat es nicht () um seine Argumentation. Wie auch immer () Sie im Argument verwenden, wird als Teil des Argumentausdrucks angesehen, nicht als Teil von sizeof Syntax selbst.

Seit my_arr ist dem Compiler als Objektname bekannt, nicht als Typname, your sizeof(my_arr)[0] wird tatsächlich vom Compiler als gesehen sizeof angewendet auf einen Ausdruck: sizeof (my_arr)[0]wo (my_arr)[0] ist der Argumentausdruck. Das () rund um den Array-Namen ist rein überflüssig. Der gesamte Ausdruck wird interpretiert als sizeof my_arr[0]. Dies entspricht Ihrem vorherigen sizeof(my_arr[0]).

(Das bedeutet übrigens, dass Ihre vorherige sizeof(my_arr[0]) enthält auch ein paar überflüssige ().)

Das ist ein weit verbreiteter Irrglaube sizeofDie Syntax von erfordert irgendwie ein Paar von () um seine Argumentation. Dieses Missverständnis führt die Intuition der Menschen in die Irre, wenn sie solche Ausdrücke wie interpretieren sizeof(my_arr)[0].

  • Die erste Version existiert, damit Sie die Größe einer Ganzzahl allgemein auf der Maschine überprüfen können (damals, als es noch nicht einmal 64-Bit-Maschinen gab!), aber int ist kein gültiger Ausdruck, daher können Sie die zweite Form damit nicht verwenden.

    – NH.

    10. Oktober 2017 um 15:46 Uhr


Benutzeravatar von mch
mch

[] haben einen höheren Vorrang als sizeof. So sizeof(my_arr)[0] ist das gleiche wie sizeof((my_arr)[0]).

Hier ist ein Link zu einer Vorrangtabelle.

Sie verwenden die Version von sizeof Operator, der einen Ausdruck als Parameter akzeptiert. Im Gegensatz zu dem, der einen Typ annimmt, ist es nicht Klammern erfordern. Daher ist der Operand einfach (my_arr)[0]wobei die Klammern überflüssig sind.

1423180cookie-checkWarum bedeutet sizeof(my_arr)[0] compilieren und gleich sizeof(my_arr[0])?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy