Gast
#6075537
Hallo, ich habe in einem code folgende Zeile gefunden
1 | |
was genau passiert da? ich teile im worst-case 1/0 ? und es wird eh nichts ausgeführt? Oder was ist der Sinn hinter dieser zeile?
|
Anzeige
|
verständnisfrage code
Gast
#6075537
Hallo, ich habe in einem code folgende Zeile gefunden
was genau passiert da? ich teile im worst-case 1/0 ? und es wird eh nichts ausgeführt? Oder was ist der Sinn hinter dieser zeile? Könnte ein verkappter static assert sein, gibt auch noch ne Variante mit nem ungültigen Arrayzugriff. Wenn die Bedingung nicht erfüllt ist knallt es bereits beim Kompilieren. Hat man früher so gemacht mangels anderer Möglichkeiten. Neuere C-Varianten (C11) unterstützen das Schlüsselwort _Static_assert Im obigen Fall hat wahrscheinlich jemand ein liebevoll handgepacktes struct gebastelt und will sicherstellen daß auch in ferner Zukunft nicht klammheimlich die Alignmentregeln sich ändern ohne daß es beim Kompilieren schon lautstark knallt mit direktem Zaunpfahlwink darauf was falsch ist (sizeof soll genau 850 sein oder irgendwas stimmt nicht). Mit _Static_assert kann man auch noch schön ne Meldung ausgeben:
In Deinem Beispiel gibts halt eine vollkommen absurde Fehlermeldung aber immerhin, es kompiliert nicht klammheimlich. Man hätte vielleicht noch einen Kommentar dazuschreiben können warum das da steht und wo vermutlich der Fehler zu suchen ist (der Programmierer hatte ein schlechtes Gewissen und kannte die wackelige Stelle ganz genau sonst hätte er diese Absicherung dort nicht errichtet) als Hinweis für zukünftige Leser die diesen alten Trick nicht kennen.
Beitrag #6075577 wurde von einem Moderator gelöscht.
Bernd K. schrieb: > Neuere C-Varianten (C11) unterstützen das Schlüsselwort _Static_assert Da nix von C da steht: in C++ heisst es: static_assert() (in C11 gibt es ein gleichlautendes Marcro dafür).
Beitrag #6075624 wurde von einem Moderator gelöscht.
Gast
#6075630
mark schrieb: > ich teile im worst-case 1/0 ? und es wird eh nichts ausgeführt? so schauts aus.. es wird nicht nur nichts ausgeführt, der Code rennt in einen divisionby0 error (der hoffentlich irgendwo behandelt wird) ich halte die Zeile für mindestens unschön ehrlich gesagt.. wenn es um die Ausführung geht reicht die zweite Hälfte völlig
macht NULL Sinn, ausser dass ein Fehlerfall ausgelöst wird falls sizeof NICHT 850 liefert beim compilieren. Aber das lässt sich mMn auch eleganter abfragen .. ein crash test header zB der sich beim release einfach wieder entfernen lässt Aber naja so macht halt jeder anders :D mark schrieb: > if (1 / ((sizeof(*parameter) == 850) ? 1 : 0)) {} Totaler Schwachsinn, denn es gibt bei -Wall -Wextra "nur" eine Warnung, und zur Laufzeit keinen Div0-Error, da wegoptimiert (auch ohne -O) Kann auch nur dort stehen, wo Statements zugelassen sind, also bspw. nicht außerhalb von Funktionen. static_assert() dagegen schon. Wilhelm M. schrieb: > Kann auch nur dort stehen, wo Statements zugelassen sind, also bspw. > nicht außerhalb von Funktionen. static_assert() dagegen schon. Dafür hat static_assert das umgekehrte Problem. Wenn man ein Macro hat, und das soll ein Resultat liefern, aber man will darin mit static_assert was prüfen, das geht nicht... Daniel A. schrieb: > Wilhelm M. schrieb: >> Kann auch nur dort stehen, wo Statements zugelassen sind, also bspw. >> nicht außerhalb von Funktionen. static_assert() dagegen schon. > > Dafür hat static_assert das umgekehrte Problem. Wenn man ein Macro hat, > und das soll ein Resultat liefern, aber man will darin mit static_assert > was prüfen, das geht nicht... Mach mal ein Beispiel bitte. So wie folgt ist/war eigentlich die gängige Methode mit alten Compilern, so kenn ich das noch von früher:
Das kann man auch in ein Makro packen:
Und dann so benutzen:
Dann kommt ungefähr so ne Meldung:
Bernd K. schrieb: > typedef char > static_assertion_bufer_size_wrong[(sizeof(buffer_descriptor_t)==8)?1:-1] ; Der "Trick" ist zumindest in der Hinsicht besser, als dass er funktioniert, und einen Compile-Zeit Fehler produziert und kein Statement ist. Trotzdem ist seine Zeit seit C11 definitiv vorbei, und sollte durch static_assert() ersetzt werden. Wilhelm M. schrieb: > Daniel A. schrieb: >> Wilhelm M. schrieb: >>> Kann auch nur dort stehen, wo Statements zugelassen sind, also bspw. >>> nicht außerhalb von Funktionen. static_assert() dagegen schon. >> >> Dafür hat static_assert das umgekehrte Problem. Wenn man ein Macro hat, >> und das soll ein Resultat liefern, aber man will darin mit static_assert >> was prüfen, das geht nicht... > > Mach mal ein Beispiel bitte. Sowas geht nicht:
Mein use-case war damals zwar etwas anders, ich wollte einen Typecheck für einer generischen linked list machen, aber das ging damals noch aus ganz anderen Gründen nicht ohne Erweiterungen (typeof) in C, also hab ichs gelassen. Bin seither schon einmal in die Falle getappt, als ich bei etwas Refactoring nicht aufpasste... Der trick mit dem negativen Array type sieht aber interessant aus. Scheint auch mit compund literalen zu gehen:
Cool. Nur dass der Komma Operator hier nicht anwendbar ist, ist etwas schade. Und jetzt muss ich mir mein Listenmakroproblem wieder anschauen, ob das nicht doch irgendwie geht... Daniel A. schrieb: > Sowas geht nicht:#include <assert.h> > > #define DEVIDE_EVEN_NUMBER_BY_TWO(X) \ > ( 0 ? static_assert((X)%2 == 0, "Must be an even number!") : X/2 ) > > int bla = DEVIDE_EVEN_NUMBER_BY_TWO(42); // Geht nicht: error: expected > expression before ‘_Static_assert’ Ja, denn static_assert() ist kein Ausdruck. Wenn ich Dich richtig verstehe, möchtest Du eine Zusicherung, die 1) in einem compile-time-constant Kontext eine compile-time Assertion ist, 2) sonst eine run-time Assertion ist. Könnte man so machen (in C++)
Fall 2) ist ja klar. Fall 1) produziert den gewünschten compile-time Fehler, weil __assert_fail(...) selbst nicht constexpr ist. Wird tatsächlich desöfteren benutzt, finde ich aber auch nur einen Hack. Für Fall 1) wäre ggf. eine andere Variante machbar:
Noch eine Variante wäre, divEven() mit als divEven(std::integral_constant<T, N>) zu überladen.
Gast
#6076188
Wilhelm M. schrieb: > Wenn ich Dich richtig verstehe, möchtest Du eine Zusicherung, die > > 1) in einem compile-time-constant Kontext eine compile-time Assertion > ist, > 2) sonst eine run-time Assertion ist. Nö, zur compile time zum compile-time-constant kontext reicht mir völlig. Aber ich nutze eben C11, da gibts keine Templates und kein constexpr, dafür muss ich dann Macros nehmen, und in gewissen Situationen brauch ich dann halt ein Macro, das mir einen Wert zurück gibt, den ich aber noch prüfen muss, weil man das Macro sonst falsch anwenden könnte, und dann muss ich alles in eine Expression reinpacken, und dann kann ich static_assert halt dort nicht mehr verwenden.
Gast
#6076217
sid schrieb: > so schauts aus.. es wird nicht nur nichts ausgeführt, > der Code rennt in einen divisionby0 error > (der hoffentlich irgendwo behandelt wird) > > ich halte die Zeile für mindestens unschön ehrlich gesagt.. > wenn es um die Ausführung geht > reicht die zweite Hälfte völligif(sizeof(*parameter) == 850){} > > macht NULL Sinn, Verstehe ich nicht. Der Compiler sieht 1/0 und soll nicht warnen? Vielleicht muss er nicht, vielleicht geht's eleganter, aber es ist doch absurd, anzunehmen, dass der dortige Compiler nicht warnt. Noch absurder ist es, das zu verbessern und dann beklagen dass das keinen Sinn mehr macht. Und das z.b. die Array-Version zuverlässiger und universeller ist: geschenkt. Ich kannte die aber auch nicht von Anfang an.
Gast
#6076388
A. S. schrieb: > Verstehe ich nicht. Der Compiler sieht 1/0 und soll nicht warnen? > Vielleicht muss er nicht, vielleicht geht's eleganter, aber es ist doch > absurd, anzunehmen, dass der dortige Compiler nicht warnt. Der compiler schmeisst (hoffentlich) n Fehler aus und warnt nicht nur (Warnungen könnten ja ignoriert werden) Ja, das sieht aber in der Tat so aus (im nachhinein) als meinte ich die vereinfachte if-kondition. Hab ich vielleicht doof formuliert.. Stell dir ein "So wie du sie im Code gefunden hast ..." davor vor :D Denn was ich meinte ist, dass es NULL Sinn macht die 'Fehlerquelle' absichtlich in die if-Kondition zu packen die (wie ich annehme) Laufzeitrelevant ist. also im kompilierten Zustand immer und immer wieder abgefragt wird. Nur um das kompilieren zu vermeiden. mMn ist es sinnvoller das in einen header zu stecken den man bei erfolgreichem Test auskommentieren kann um sauberere und besser lesbaren Quellcode zu haben.
Gast
#6076515
sid schrieb: > Denn was ich meinte ist, > dass es NULL Sinn macht die 'Fehlerquelle' absichtlich > in die if-Kondition zu packen die (wie ich annehme) Laufzeitrelevant > ist. > also im kompilierten Zustand immer und immer wieder abgefragt wird. > Nur um das kompilieren zu vermeiden. ich würde annahmen, der TO hat den vollständigen Code gepostet. Also eine Leere Schleife mit dieser if-Abfrage, die vom Compiler (oder wem auch immer) komplett entfernt wird. Aber klar, ein define, dass dann einfach nur "sAssert(850 == sizeof *parameter);" erlaubt, wäre auch vor C11 schöner. Nur wie gesagt, dass war vor Jahren nicht Standard. Ich habe es auch erst vor ~15 Jahren irgendwo zufällig kennengelernt (mit []), als erster unter uns Kollegen. Wenn das jemand selbst erdacht hat: Alle Achtung.
Gast
#6077034
Writer schrieb: > ich würde annahmen, der TO hat den vollständigen Code gepostet. Also > eine Leere Schleife mit dieser if-Abfrage, die vom Compiler (oder wem > auch immer) komplett entfernt wird. Ah siehste.. das hab ich anders gedeutet.. dann natürlich spielt es wirklich keine Rolle (wird ja wegrationalisiert) Aber so ist das halt.. am Ende des Tages erkennt man Programmierer and ihrem Dialekt wieder ;) Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|