Was ist die Funktion von “(void) (&_min1 == &_min2)” im min-Makro in kernel.h?

Lesezeit: 5 Minuten

Benutzeravatar von Robert S. Barnes
Robert S. Barnes

Im Kernel.h min ist definiert als:

#define min(x, y) ({                \
    typeof(x) _min1 = (x);          \
    typeof(y) _min2 = (y);          \
    (void) (&_min1 == &_min2);      \
    _min1 < _min2 ? _min1 : _min2; })

Ich verstehe nicht, was die Zeile (void) (&_min1 == &_min2); tut. Ist das eine Art Typprüfung oder so?

  • Neugierig. Es scheint mir, dass der Adressvergleich _min1 und _min2 und damit x und y dazu zwingen würde, tatsächlich berechnet und gespeichert zu werden, aber sollte das nicht sowieso passieren, wenn _min1 in der nächsten Zeile mit _min2 verglichen wird?

    – michel-slm

    8. April 2011 um 13:21 Uhr

  • FYI, die Frage Makro mit einer ungewöhnlichen Zeile im Linux-Kernel? wurde mit diesem zusammengeführt, so dass Sie jetzt ein paar neue Antworten haben.

    – Shafik Yaghmour

    14. November 2014 um 1:52 Uhr

Benutzeravatar von pmg
pmg

Die Aussage

(void) (&_min1 == &_min2);

ist ein garantiertes “no-op”. Der einzige Grund, warum es da ist, sind seine Nebenwirkungen.

Aber die Aussage hat keine Nebenwirkungen!

Jedoch: es zwingt den Compiler, eine Diagnose auszugeben, wenn die Typen von x und y sind nicht kompatibel.
Beachten Sie, dass das Testen mit _min1 == _min2 würde implizit einen der Werte in den anderen Typ konvertieren.

Das tut es also. Es validiert zur Kompilierzeit, dass die Typen von x und y kompatibel sind.

  • Vielleicht ist es besser zu sagen, dass es nein hat Laufzeit Nebenwirkungen, sondern eher Zusammenstellung Nebenwirkungen.

    – J. Pölfer

    8. April 2011 um 13:28 Uhr

  • Das klingt für mich aus irgendeinem Grund nicht richtig. Wenn die Typen nicht kompatibel sind, funktioniert das Makro sowieso nicht. Das heißt, wenn Sie dem Makro ein struct foo und ein int übergeben, erhalten Sie sowieso einen Kompilierungsfehler, auch ohne diese Zeile.

    – Robert S.Barnes

    8. April 2011 um 14:11 Uhr


  • @Robert: Versuchen Sie zum Beispiel, m = min(42, 43.0);. Sowohl mit als auch ohne die fragliche Aussage.

    – pmg

    8. April 2011 um 14:18 Uhr


  • @pmg: Es geht also nicht um inkompatible Typen, sondern darum, dass beide Argumente vom gleichen Typ sind?

    – Robert S.Barnes

    8. April 2011 um 14:21 Uhr

  • int und volatile const int sind unterschiedliche, aber kompatible Typen!

    – pmg

    8. April 2011 um 14:29 Uhr

Benutzeravatar von Hasturkun
Hasturkun

Der Code drin include/linux/kernel.h bezeichnet dies als “unnötigen” Zeigervergleich. Dies ist in der Tat eine strenge Typprüfung, die sicherstellt, dass die Typen von x und y sind gleich.

Ein Typkonflikt führt hier zu einem Kompilierungsfehler oder einer Warnung.

  • Aber was passiert, wenn sie nicht gleich sind? Scheint so, als ob der Code trotzdem ausgeführt wird.

    – Benutzer10607

    3. November 2014 um 15:53 ​​Uhr

  • Verschwendet das nicht CPU-Zeit für die Gleichheitsprüfung?

    – Nico

    3. November 2014 um 17:42 Uhr

  • Nein, es ist ein Nop. Es wird im void-Kontext aufgerufen, sodass die Ergebnisse keine Rolle spielen, ein Optimierer würde es vollständig eliminieren.

    – Hasturkun

    3. November 2014 um 17:43 Uhr

  • @ user10607: Ja. Es hat keinerlei Nebenwirkungen und seine Ergebnisse werden verworfen, es gäbe keinen Grund, es zu behalten.

    – Hasturkun

    3. November 2014 um 18:45 Uhr

  • @ user10607: Nein. Es wird kompiliert (wo die Magie der Typprüfung auftritt) und später vom Optimierer verworfen (noch während der Kompilierungsphase).

    – Hasturkun

    3. November 2014 um 19:42 Uhr

Benutzeravatar von Shafik Yaghmour
Shafik Yaghmur

Dies sorgt für Typüberprüfung, Gleichheit zwischen Zeigern muss zwischen kompatiblen Typen und sein gcc wird in Fällen, in denen dies nicht der Fall ist, eine Warnung ausgeben.

Wir können sehen, dass die Gleichheit zwischen Zeigern erfordert, dass die Zeiger von sind kompatible Typen von dem Entwurf des C99-Standards Sektion 6.5.9 Gleichheitsoperatoren was sagt:

Einer der folgenden Punkte gilt:

und beinhaltet:

beide Operanden sind Zeiger auf qualifizierte oder nicht qualifizierte Versionen kompatibler Typen;

und wir können finden, was a kompatibler Typ ist aus der Sektion 6.2.7 Kompatibler Typ und zusammengesetzter Typ was sagt:

Zwei Typen haben einen kompatiblen Typ, wenn ihre Typen gleich sind

Diese Diskussion auf osnews deckt auch diese ab und wurde von der inspiriert GCC-Hacks im Linux-Kernel Artikel, der das gleiche Codebeispiel enthält. Die Antwort sagt:

hat was mit Typenprüfung zu tun.

Erstellen eines einfachen Programms:

int x = 10; 
long y = 20;
long r = min(x, y);

Gibt die folgende Warnung aus: Warnung: Beim Vergleich unterschiedlicher Zeigertypen fehlt eine Umwandlung

  • Zusammengeführt von stackoverflow.com/questions/26717636/…

    – Shog9

    13. November 2014 um 21:26 Uhr

Sehen http://www.osnews.com/comments/20566 was erklärt:

Das hat mit Typprüfung zu tun.

Erstellen eines einfachen Programms:

int x = 10; 
long y = 20; 
long r = min(x, y); 

Gibt die folgende Warnung aus: Warnung: Beim Vergleich unterschiedlicher Zeigertypen fehlt eine Umwandlung

Antwort gefunden hier

„Das hat mit Typechecking zu tun. Ein einfaches Programm erstellen:

int x = 10; 
long y = 20; 
long r = min(x, y); 

Gibt die folgende Warnung aus: Warnung: Beim Vergleich unterschiedlicher Zeigertypen fehlt eine Umwandlung.

  • Zusammengeführt von stackoverflow.com/questions/26717636/…

    – Shog9

    13. November 2014 um 21:26 Uhr

R.. GitHub STOP HELPING ICEs Benutzeravatar
R.. GitHub HÖREN SIE AUF, ICE ZU HELFEN

Der Linux-Kernel ist voll von solchem ​​Zeug (unentgeltliche gcc-spezifische Hacks aus Gründen der “Typsicherheit” und anderer ähnlicher Überlegungen), und ich würde es als sehr schlechte Praxis betrachten und Sie dringend bitten, es nicht zu befolgen, es sei denn, jemand verlangt es von Ihnen.

pmg hat Recht mit dem Zweck des Hacks, aber jeder vernünftige Mensch würde es definieren min wie ((x)<(y)?(x):(y)).

Beachten Sie, dass die Kernel-Definition viele korrekte Verwendungen ausschließt, zB wo ein Argument ist int und ein anderer ist long. Ich vermute, was sie wirklich ausschließen wollten, sind Vorzeichenkonflikte, wo zum Beispiel min(-1,1U) ist 1. Ein besserer Weg, dies zu bestätigen, wäre die Verwendung einer Kompilierzeit-Assertion für ((1?-1:(x))<0)==((1?-1:(y))<0). Beachten Sie, dass hierfür keine gcc-spezifischen Hacks erforderlich sind.

  • Zusammengeführt von stackoverflow.com/questions/26717636/…

    – Shog9

    13. November 2014 um 21:26 Uhr

1414230cookie-checkWas ist die Funktion von “(void) (&_min1 == &_min2)” im min-Makro in kernel.h?

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

Privacy policy