Wie vergleicht man Strukturen auf Gleichheit in C?

Lesezeit: 6 Minuten

Wie vergleichen Sie zwei Instanzen von Strukturen auf Gleichheit in Standard-C?

C bietet dafür keine Spracheinrichtungen – Sie müssen es selbst tun und jedes Strukturelement für Element vergleichen.

  • Wenn die 2-Strukturen-Variablen mit calloc initialisiert oder von memset auf 0 gesetzt werden, können Sie Ihre 2-Strukturen mit memcmp vergleichen, und Sie müssen sich keine Gedanken über Strukturmüll machen, und dies ermöglicht es Ihnen, Zeit zu gewinnen

    – MOHAMED

    3. Oktober 2012 um 9:09 Uhr

  • @MOHAMED Vergleich von Gleitkommafeldern mit 0.0, -0.0 NaN ist ein Problem mit memcmp(). Zeiger, die sich in der binären Darstellung unterscheiden, können auf dieselbe Stelle zeigen (z. B. DOS: seg:offset) und sind daher gleich. Einige Systeme haben mehrere Nullzeiger, die sich gleichermaßen vergleichen lassen. Gleiches gilt für obskur int mit -0 und Fließkommatypen mit redundanten Kodierungen. (Intel long double, decimal64 usw.) Diese Punkte machen keinen Unterschied calloc() verwendet oder nicht oder Polsterung.

    – chux – Wiedereinsetzung von Monica

    14. April 2015 um 15:02 Uhr


  • @chux An irgendein Modernes 32- oder 64-Bit-System, das ich kenne, das einzige Problem ist die Gleitkommazahl.

    – Demi

    21. September 2017 um 0:11 Uhr

  • Falls Sie sich fragen, warum == arbeitet nicht mit Strukturen (wie ich), siehe stackoverflow.com/questions/46995631/…

    – stefankt

    28. Oktober 2017 um 23:57 Uhr

  • @Demi: Heute. Das 10. Gebot für C-Programmierer lautet: ‘Du sollst der abscheulichen Häresie, die behauptet, dass ‘Die ganze Welt ein VAX’ ist, abschwören, sie aufgeben und ihr abschwören …’. Dies durch “All the world’s a PC” zu ersetzen, ist keine Verbesserung.

    – Martin Bonner unterstützt Monika

    21. Dezember 2017 um 17:11 Uhr

Benutzeravatar von Sufian
Sufian

Sie könnten versucht sein, es zu verwenden memcmp(&a, &b, sizeof(struct foo)), aber es funktioniert möglicherweise nicht in allen Situationen. Der Compiler kann einer Struktur Ausrichtungspufferraum hinzufügen, und die Werte, die an Speicherorten gefunden werden, die im Pufferraum liegen, sind nicht garantiert irgendein bestimmter Wert.

Aber, wenn Sie verwenden calloc oder memset die volle Größe der Strukturen, bevor Sie sie verwenden, Sie kann mach ein seicht im Vergleich mit memcmp (Wenn Ihre Struktur Zeiger enthält, wird sie nur übereinstimmen, wenn die Adresse, auf die die Zeiger zeigen, dieselbe ist).

  • Schließen, weil es auf “fast allen” Compilern funktioniert, aber nicht ganz. Überprüfen Sie 6.2.1.6.4 in C90: “Zwei Werte (außer NaNs) mit derselben Objektdarstellung sind gleich, aber Werte, die gleich sind, können unterschiedliche Objektdarstellungen haben.”

    – Steve Jessop

    26. September 2008 um 22:43 Uhr

  • Stellen Sie sich ein “BOOL”-Feld vor. In Bezug auf die Gleichheit ist jeder BOOL-Wert ungleich Null gleich jedem BOOL-Wert ungleich Null. Während also 1 und 2 beide TRUE und daher gleich sein können, wird memcmp fehlschlagen.

    – ajs410

    16. April 2013 um 3:41 Uhr

  • @JSalazar Vielleicht einfacher für dich, aber viel schwieriger für den Compiler und die CPU und damit auch viel langsamer. Warum denken Sie, dass der Compiler überhaupt Padding hinzufügt? Sicherlich nicht um umsonst Speicher zu verschwenden 😉

    – Mecki

    31. März 2014 um 22:48 Uhr

  • @Demetri: Zum Beispiel sind die Float-Werte positive und negative Null bei jeder IEEE-Float-Implementierung gleich, aber sie haben nicht dieselbe Objektdarstellung. Eigentlich hätte ich nicht sagen sollen, dass es auf “fast allen Compilern” funktioniert, es wird bei jeder Implementierung fehlschlagen, die Sie eine negative Null speichern lässt. Ich habe wahrscheinlich an lustige ganzzahlige Darstellungen gedacht, als ich den Kommentar machte.

    – Steve Jessop

    19. August 2015 um 13:35 Uhr


  • @Demetri: aber viele enthalten Floats, und der Fragesteller fragt “Wie vergleicht man Strukturen”, nicht “Wie vergleicht man Strukturen, die keine Floats enthalten”. Diese Antwort besagt, dass Sie einen flachen Vergleich durchführen können memcmp Vorausgesetzt, der Speicher wurde zuvor gelöscht. Was fast funktioniert, aber nicht richtig ist. Natürlich definiert die Frage auch nicht “Gleichheit”, wenn Sie also “byteweise Gleichheit der Objektdarstellung” meinen memcmp tut genau das (ob der Speicher gelöscht ist oder nicht).

    – Steve Jessop

    20. August 2015 um 12:12 Uhr


Wenn Sie es oft tun, würde ich vorschlagen, eine Funktion zu schreiben, die die beiden Strukturen vergleicht. Wenn Sie also jemals die Struktur ändern, müssen Sie den Vergleich nur an einer Stelle ändern.

Wie es geht …. Sie müssen jedes Element einzeln vergleichen

  • Ich würde eine separate Funktion schreiben, selbst wenn ich sie nur einmal verwenden würde.

    – Sam

    8. November 2018 um 9:32 Uhr

Sie können memcmp nicht verwenden, um Strukturen auf Gleichheit zu vergleichen, da möglicherweise zufällige Füllzeichen zwischen Feldern in Strukturen vorhanden sind.

  // bad
  memcmp(&struct1, &struct2, sizeof(struct1));

Das obige würde für eine Struktur wie diese fehlschlagen:

typedef struct Foo {
  char a;
  /* padding */
  double d;
  /* padding */
  char e;
  /* padding */
  int f;
} Foo ;

Sie müssen mitgliederweise Vergleiche verwenden, um auf der sicheren Seite zu sein.

Benutzeravatar von Demi
Demi

@Greg ist richtig, dass man im allgemeinen Fall explizite Vergleichsfunktionen schreiben muss.

Es ist möglich zu verwenden memcmp wenn:

  • die Strukturen enthalten keine Gleitkommafelder, die möglicherweise sind NaN.
  • die Strukturen enthalten kein Padding (use -Wpadded mit clang, um dies zu überprüfen) ODER die Strukturen werden explizit mit initialisiert memset bei der Initialisierung.
  • Es gibt keine Mitgliedstypen (wie Windows BOOL), die unterschiedliche, aber gleichwertige Werte haben.

Wenn Sie nicht für eingebettete Systeme programmieren (oder eine Bibliothek schreiben, die auf ihnen verwendet werden könnte), würde ich mir über einige der Eckfälle im C-Standard keine Gedanken machen. Die Unterscheidung zwischen nahem und fernem Zeiger existiert nicht auf 32- oder 64-Bit-Geräten. Kein nicht eingebettetes System, das ich kenne, hat mehrere NULL Zeiger.

Eine weitere Option besteht darin, die Gleichheitsfunktionen automatisch zu generieren. Wenn Sie Ihre Strukturdefinitionen auf einfache Weise anordnen, ist es möglich, einfache Textverarbeitung zu verwenden, um einfache Strukturdefinitionen zu handhaben. Sie können libclang für den allgemeinen Fall verwenden – da es dasselbe Frontend wie Clang verwendet, behandelt es alle Eckfälle korrekt (mit Ausnahme von Fehlern).

Ich habe noch nie eine solche Codegenerierungsbibliothek gesehen. Es scheint jedoch relativ einfach zu sein.

Es ist jedoch auch so, dass solche generierten Gleichheitsfunktionen auf Anwendungsebene oft das Falsche tun würden. Zum Beispiel sollten zwei UNICODE_STRING Strukturen in Windows oberflächlich oder tief verglichen werden?

  • Explizite Initialisierung der Strukturen mit memsetusw. garantiert nicht den Wert der Füllbits nach dem weiteren Schreiben in ein Strukturelement, siehe: stackoverflow.com/q/52684192/689161

    – gengkev

    11. Oktober 2018 um 14:15 Uhr

Benutzeravatar von pixelbeat
Pixelschlag

Beachten Sie, dass Sie memcmp() für nicht statische Strukturen verwenden können, ohne sich Gedanken über das Auffüllen zu machen, solange Sie nicht alle Mitglieder (auf einmal) initialisieren. Dies wird durch C90 definiert:

http://www.pixelbeat.org/programming/gcc/auto_init.html

  • Explizite Initialisierung der Strukturen mit memsetusw. garantiert nicht den Wert der Füllbits nach dem weiteren Schreiben in ein Strukturelement, siehe: stackoverflow.com/q/52684192/689161

    – gengkev

    11. Oktober 2018 um 14:15 Uhr

Benutzeravatar von domgblackwell
domgblackwell

Es hängt davon ab, ob die Frage, die Sie stellen, lautet:

  1. Sind diese beiden Strukturen dasselbe Objekt?
  2. Haben sie den gleichen Wert?

Um herauszufinden, ob es sich um dasselbe Objekt handelt, vergleichen Sie Zeiger auf die beiden Strukturen auf Gleichheit. Wenn Sie im Allgemeinen herausfinden möchten, ob sie den gleichen Wert haben, müssen Sie einen tiefen Vergleich durchführen. Dabei werden alle Mitglieder verglichen. Wenn die Mitglieder Zeiger auf andere Strukturen sind, müssen Sie auch in diese Strukturen rekursieren.

In dem speziellen Fall, in dem die Strukturen keine Zeiger enthalten, können Sie einen memcmp ausführen, um einen bitweisen Vergleich der darin enthaltenen Daten durchzuführen, ohne wissen zu müssen, was die Daten bedeuten.

Stellen Sie sicher, dass Sie wissen, was “gleich” für jedes Mitglied bedeutet – es ist offensichtlich für Ganzzahlen, aber subtiler, wenn es um Gleitkommawerte oder benutzerdefinierte Typen geht.

1426230cookie-checkWie vergleicht man Strukturen auf Gleichheit in C?

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

Privacy policy