sizeof mit einem Typ oder einer Variablen

Lesezeit: 8 Minuten

Benutzeravatar von jmucchiello
jmucchiello

Kürzlich sah ich jemanden, der einen anderen Benutzer für die Verwendung von sizeof var anstelle von sizeof(type) lobte. Ich dachte immer, das sei nur eine Stilentscheidung. Gibt es einen signifikanten Unterschied? Als Beispiel wurden die Zeilen mit f und ff als besser angesehen als die Zeilen mit g und gg:

 typedef struct _foo {} foo;

 foo *f = malloc(count * sizeof f);
 foo *g = malloc(sizeof(foo) * count);

 foo **ff = malloc(count * sizeof *ff);
 foo **gg = malloc(sizeof(foo*) * count);

Meiner Meinung nach ist das erste Set nur eine Frage des Stils. Aber im zweiten Zeilenpaar kann die zusätzliche Sekunde * leicht mit einer Multiplikation verwechselt werden.

  • Sie haben einen Fehler in Ihrer ersten malloc Linie – es sollte sein sizeof *f. Das allgemeine Muster ist somevar = malloc(count * sizeof *somevar).

    – Café

    22. Dezember 2009 um 5:13 Uhr

  • malloc(sizeof(foo[count])) funktioniert auch

    – tstanisl

    19. Oktober 2021 um 9:46 Uhr

Benutzeravatar von Steve Fallows
Steve Fallows

Wenn der Typ der Variablen geändert wird, muss sizeof nicht geändert werden, wenn die Variable das Argument und nicht der Typ ist.

In Bezug auf den Kommentar von @icepack: Die Möglichkeit oder Wahrscheinlichkeit einer Änderung des Typs gegenüber dem Variablennamen ist nicht das Problem. Stellen Sie sich vor, der Variablenname wird als Argument für sizeof verwendet und später geändert. Im besten Fall ändert eine Refactor-Rename-Operation alle Vorkommen und es wird kein Fehler eingeführt. Im schlimmsten Fall wird eine Instanz eines sizeof übersehen und der Compiler beschwert sich und Sie beheben es. Wenn der Typ geändert wird, sind Sie fertig, keine Möglichkeit von Fehlern bei sizeof-Anweisungen.

Stellen Sie sich nun vor, dass der Typ das Argument für sizeof ist. Wenn der Typ der Variablen geändert wird, gibt es keine andere Möglichkeit als die Überprüfung, um alle Größen zu finden, die sich auf diese Variable beziehen. Sie können suchen, aber Sie erhalten Treffer für alle nicht verwandten Verwendungen von sizeof desselben Typs. Wenn eine fehlt, haben Sie ein Laufzeitproblem aufgrund eines Größenunterschieds, der viel schwieriger zu finden ist.

  • Bei Array-Variablen liefert sizeof(array) die tatsächliche Größe des Arrays. Es kann verwendet werden, um die Anzahl der Elemente sizeof(array)/sizeof(element) zu berechnen. Beachten Sie, dass dies nicht für dynamisch zugewiesenen Speicher über einen Zeiger funktioniert.

    – David Rodríguez – Dribeas

    17. Dezember 2008 um 7:24 Uhr

  • Keine plausible Argumentation. Auf die gleiche Weise ist es möglich zu behaupten, dass, wenn der Name der Variablen geändert wird, die Größe von nicht geändert werden muss, wenn der Typ das Argument und nicht die Variable ist. Die Möglichkeit der Änderung für beide hängt vom spezifischen Design ab (und in den meisten Fällen wird oder sollte sich keines der beiden ändern)

    – SomeWittyBenutzername

    8. Dezember 2012 um 8:25 Uhr

  • Diese Antwort scheint keine “endgültige” Lösung zu sein, wenn man bedenkt, dass sie keine Fälle abdeckt, in denen die Codelogik eher von einer Typedef als von einer bestimmten Variablen abhängt. Sie können meine Antwort unten sehen.

    – Riga

    20. Mai 2014 um 11:13 Uhr

Lassen Sie mich zusätzlich zu dem, was Steve sagt, hinzufügen, dass sizeof seinen Operanden nicht auswertet. Sie können also alles darin tun. Sie können nicht nur noch nicht initialisierte Variablen verwenden, sondern auch einen Nullzeiger dereferenzieren, nicht definierte, sondern nur deklarierte Funktionen aufrufen und andere Dinge tun. Ich ermutige Sie, immer die Ausdrucksversion zu verwenden, aus Gründen, die Steve großartig erklärt hat.

Denken Sie auch daran, dass Typnamen manchmal sehr lang und unlesbar sind, denken Sie nur an Zeiger auf Funktionen (insbesondere in C++). Anstatt zu schreiben sizeof(my_long_type<weird, stuff>) du tust es einfach sizeof t.

  • 4 Jahre sind vergangen und das Problem der langen Typnamen in C++ hat sich verringert decltype 🙂

    – SomeWittyBenutzername

    8. Dezember 2012 um 8:28 Uhr

Möglicherweise sehen Sie einen kleinen Unterschied zwischen diesen:

foo **ff = malloc(count * sizeof *ff);
foo **gg = malloc(sizeof(foo*) * count);

..aber was ist, wenn die Zuordnung nicht in der Nähe der Deklaration liegt? Wenn ich auf eine Zeile stoße wie:

ff = realloc(ff, count * sizeof *ff);

dann bin ich ziemlich sicher, dass die Zeile richtig ist, ohne mich auch nur an die Art zu erinnern ff. Aber wenn ich das sehe:

ff = realloc(ff, count * sizeof(foo *));

Dann bin ich vielleicht etwas misstrauisch und muss nach der Art von suchen ff um mich zu beruhigen.

Die Zeilen f und ff sind definitiv schlechter als g und gg. sizeof f ist die Zeigergröße, da f ein Punkt ist. Um sie gleichwertig zu machen, müssten Sie schreiben sizeof *f (oder zur besseren Lesbarkeit sizeof(*f)).

Benutzeravatar von Jonathan Leffler
Jonathan Leffler

Ich neige dazu zu verwenden sizeof(type) in der Speicherzuweisung, aber immer sizeof(variable) bei Verwendung einer lokalen oder globalen Variablen. Dennoch ist es klug, immer den Variablennamen zu verwenden.

Ich hatte auch eine lange Diskussion (manchmal ziemlich angeregt, und sie dauerte mehrere Tage – wir waren uns schließlich einig, dass wir uns in dieser Frage nicht einig waren) darüber, ob die Verwendung in Ordnung ist sizeof(variable) oder ob es sein muss sizeof variable; das heißt, spielt es eine Rolle, ob Klammern das Argument umschließen sizeof. Ich bin noch nie auf einen Compiler gestoßen, über den gewittert wird sizeof(variable)also entscheide ich mich für Einheitlichkeit und verwende immer die Klammern mit sizeof. Mein Kollege bestand ebenso darauf, dass Klammern nicht mit Variablen verwendet werden dürfen; dass es irgendwie einen wertvollen Unterschied zwischen der Notation mit und ohne Klammern gibt / gab. Ich bin nicht überzeugt worden – ich erwarte nicht, überzeugt zu werden.

Auf einem ganz anderen Kurs, ein paar andere Punkte darüber sizeof:

  • Wenn Sie C99 und VLA (Arrays mit variabler Länge) verwenden, dann sizeof(vla) ist keine Kompilierzeitkonstante. In acht nehmen!
  • Der C-Präprozessor versteht das nicht sizeof das ist ärgerlich, aber logisch.

  • Sieht so aus, als hätten Sie hier eine weitere fragliche Frage. Mein Verständnis ist, dass sizeof eine Kompilierzeitsache ist, obwohl es irgendwie wie eine (Bibliotheks-) Funktion aussieht und funktioniert. Vielleicht will er, dass es anders aussieht. Ich benutze es nicht genug, um eine Rolle zu spielen. Andererseits habe ich Blicke bekommen, weil ich “return(x);” gemacht habe.

    – gbarry

    19. Dezember 2008 um 7:33 Uhr

  • Am häufigsten verwende ich Klammern um den Rückgabewert. Ich weiß, dass einige Leute darüber entsetzt sind, aber es funktioniert für mich. Ich bin nicht verwirrt darüber, ob return oder sizeof ‘Funktionen’ sind.

    – Jonathan Leffler

    19. Dezember 2008 um 15:33 Uhr

  • Ich hasse Klammern bei der Rückgabe, hauptsächlich weil es unnötig ist. Klammern nach sizeof können die Lesbarkeit verbessern: malloc(sizeof(*f)*10) ist viel einfacher zu verstehen als malloc(sizeof *f*10).

    – Jmucchiello

    19. Dezember 2008 um 17:43 Uhr

  • Ich erinnere mich an die Regel, die in meinem Kopf verwurzelt ist, keine Klammern zu verwenden, wenn sizeof für eine Variable ausgeführt wird. Ich denke, das Buch von K & R sagt dazu, aber ich stimme in der Praxis zu, dass Sie immer mit Klammern davonkommen können.

    – nosatalisch

    5. April 2011 um 22:17 Uhr

  • Ich verwende einen Compiler, der Klammern erfordert, wenn der Parameter ein Typ ist (und ansonsten “Typname ist nicht zulässig”) zurückgibt. Ich bin mir nicht sicher, ob das laut Standard richtig ist, der Compiler soll C99-konform sein.

    – Gauthier

    11. August 2011 um 21:05 Uhr

Benutzeravatar von SoapBox
Seifenkiste

Das Ermitteln der Größe einer Variablen kann zu unerwarteten Ergebnissen führen. Wenn die Variable ein Array ist, gibt sizeof(array) die Größe des Arrays zurück, nicht die Größe eines einzelnen Elements oder die Größe eines Zeigers. Wenn Sie die Größe eines Zeigers nehmen, wird die Größe eines Zeigers zurückgegeben. Aber da Arrays normalerweise als Zeiger dargestellt werden, wenn sie herumgereicht werden, kann die Sache verwirrend werden.

  • Sieht so aus, als hätten Sie hier eine weitere fragliche Frage. Mein Verständnis ist, dass sizeof eine Kompilierzeitsache ist, obwohl es irgendwie wie eine (Bibliotheks-) Funktion aussieht und funktioniert. Vielleicht will er, dass es anders aussieht. Ich benutze es nicht genug, um eine Rolle zu spielen. Andererseits habe ich Blicke bekommen, weil ich “return(x);” gemacht habe.

    – gbarry

    19. Dezember 2008 um 7:33 Uhr

  • Am häufigsten verwende ich Klammern um den Rückgabewert. Ich weiß, dass einige Leute darüber entsetzt sind, aber es funktioniert für mich. Ich bin nicht verwirrt darüber, ob return oder sizeof ‘Funktionen’ sind.

    – Jonathan Leffler

    19. Dezember 2008 um 15:33 Uhr

  • Ich hasse Klammern bei der Rückgabe, hauptsächlich weil es unnötig ist. Klammern nach sizeof können die Lesbarkeit verbessern: malloc(sizeof(*f)*10) ist viel einfacher zu verstehen als malloc(sizeof *f*10).

    – Jmucchiello

    19. Dezember 2008 um 17:43 Uhr

  • Ich erinnere mich an die Regel, die in meinem Kopf verwurzelt ist, keine Klammern zu verwenden, wenn sizeof für eine Variable ausgeführt wird. Ich denke, das Buch von K & R sagt dazu, aber ich stimme in der Praxis zu, dass Sie immer mit Klammern davonkommen können.

    – nosatalisch

    5. April 2011 um 22:17 Uhr

  • Ich verwende einen Compiler, der Klammern erfordert, wenn der Parameter ein Typ ist (und ansonsten “Typname ist nicht zulässig”) zurückgibt. Ich bin mir nicht sicher, ob das laut Standard richtig ist, der Compiler soll C99-konform sein.

    – Gauthier

    11. August 2011 um 21:05 Uhr

Benutzeravatar von Riga
Riga

Die Geschäftslogik bestimmt Ihre Wahl.

  1. Wenn sich Ihr Code auf eine bestimmte Variable bezieht und Ihr Code ohne diese Variable keinen Sinn macht – wählen Sie sizeof(var)

  2. Wenn Sie Code mit einer Reihe von Variablen mit einem bestimmten Typ zu tun haben – wählen Sie sizeof(type). Normalerweise benötigen Sie dies, wenn Sie eine haben typedef die viele Variablen definiert, die Sie aufgrund ihres Typs (z. B. Serialisierung) unterschiedlich verarbeiten. Möglicherweise wissen Sie nicht, welche dieser Variablen in zukünftigen Codeversionen verbleiben werden, daher ist die Auswahl von type als Argument logisch korrekt. Auch das Wechseln solcher typedef wird Ihre nicht beeinträchtigen sizeof Linie.

1433520cookie-checksizeof mit einem Typ oder einer Variablen

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

Privacy policy