Inkonsistenter strcmp()-Rückgabewert bei der Übergabe von Strings als Zeiger oder als Literale

Lesezeit: 6 Minuten

Inkonsistenter strcmp Ruckgabewert bei der Ubergabe von Strings als Zeiger oder
Ahmad AL-wazzan

Ich spielte herum mit strcmp Als mir das aufgefallen ist, hier der Code:

#include <string.h>
#include <stdio.h>

int main(){

    //passing strings directly
    printf("%dn", strcmp("ahmad", "fatema"));

    //passing strings as pointers 
    char *a= "ahmad";
    char *b= "fatema";
    printf("%dn",strcmp(a,b));

    return 0;

}

die Ausgabe ist:

-1
-5

sollte nicht strcmp gleich arbeiten? Warum erhalte ich einen anderen Wert, wenn ich Strings als übergebe? "ahmad" oder als char* a = "ahmad". Wenn Sie Werte an eine Funktion übergeben, werden sie in ihrem Stack zugewiesen, oder?

  • Kompilieren mit gcc -O0 -g3 es passiert mir.

    – Iharob Al Asimi

    3. Januar ’15 um 2:45


  • @Barmar habe ich eingeschlossen <string.h> in meinem Fall, und das OP hat Recht.

    – Iharob Al Asimi

    3. Januar ’15 um 2:46

  • Das Verhalten ist richtig. Der Rückgabewert ist in beiden Fällen negativ. Was ist hier das Problem?

    – davmac

    3. Januar ’15 um 2:47

  • @Hackaholic die beiden unterschiedlichen Rückgabewerte haben laut Definition der Funktion genau die gleiche Bedeutung.

    – davmac

    3. Januar ’15 um 2:51

  • @Wintermute – Da der Standard keine Garantien für den Rückgabewert von gibt strcmp Ansonsten ist es negativ, null oder positiv, das einzige Mal, auf das Sie sich wirklich verlassen können strcmp(a,b) == strcmp(c,d) wahr ist, wenn beide Vergleiche null ergeben.

    – David Hammen

    3. Januar ’15 bei 3:42

1642023245 761 Inkonsistenter strcmp Ruckgabewert bei der Ubergabe von Strings als Zeiger oder
Shafik Yaghmour

Sie sehen höchstwahrscheinlich das Ergebnis einer Compiler-Optimierung. Wenn wir teste den Code mit gcc auf Godbolt, mit -O0 Optimierungsstufe, wir können für den ersten Fall sehen, dass es nicht aufruft strcmp:

movl    $-1, %esi   #,
movl    $.LC0, %edi #,
movl    $0, %eax    #,
call    printf  #

Da Sie Konstanten als Argumente verwenden, um strcmp der Compiler kann performen ständiges Falten und ruf an Compiler-intrinsisch zur Kompilierzeit und generieren Sie die -1 dann, anstatt anrufen zu müssen strcmp zur Laufzeit, die in der Standardbibliothek implementiert ist und eine andere Implementierung hat als eine wahrscheinlich einfachere Kompilierzeit strcmp.

Im zweiten Fall erzeugt es einen Aufruf an strcmp:

call    strcmp  #
movl    %eax, %esi  # D.2047,
movl    $.LC0, %edi #,
movl    $0, %eax    #,
call    printf  #

Dies steht im Einklang mit der Tatsache, dass gcc hat ein eingebautes für strcmp, welches ist was gcc wird während des ständigen Faltens verwendet.

Wenn wir weiter testen mit -O1 Optimierungslevel oder höher gcc kann beide Fälle falten und das Ergebnis ist -1 für beide Fälle:

movl    $-1, %esi   #,
movl    $.LC0, %edi #,
xorl    %eax, %eax  #
call    printf  #
movl    $-1, %esi   #,
movl    $.LC0, %edi #,
xorl    %eax, %eax  #
call    printf  #

Wenn weitere Optimierungsoptionen aktiviert sind, kann der Optimierer feststellen, dass a und b zeigen auch auf Konstanten, die zur Kompilierzeit bekannt sind, und kann auch das Ergebnis von berechnen strcmp auch in diesem Fall während der Kompilierzeit.

Das können wir bestätigen gcc verwendet die eingebaute Funktion, indem es mit dem baut -fno-integriertes Flag und beobachten, dass ein Aufruf an strcmp wird für alle Fälle generiert.

clang ist etwas anders, da es sich bei Verwendung überhaupt nicht zusammenfaltet -O0 aber wird falten bei -O1 und oben für beide.

Beachten Sie, dass jedes negative Ergebnis vollständig konform ist, wie wir im Abschnitt zum Entwurf des C99-Standards sehen können 7.21.4.2 Die strcmp-Funktion, die sagt (Betonung von mir):

int strcmp(const char *s1, const char *s2);

Die Funktion strcmp gibt eine ganze Zahl zurück, die größer als gleich ist. oder kleiner als null, dementsprechend ist die Zeichenfolge, auf die s1 zeigt, größer als, gleich oder weniger als die Schnur auf s2 hingewiesen.

technosurus weist darauf hin strcmp wird angegeben, um die Zeichenfolgen so zu behandeln, als ob sie aus zusammengesetzt wären unsigniertes Zeichen, dies wird in C99 unter . behandelt 7.21.1 was sagt:

Für alle Funktionen in diesem Unterabschnitt ist jedes Zeichen so zu interpretieren, als ob es den Typ unsigned char hätte (daher ist jede mögliche Objektdarstellung gültig und hat einen anderen Wert).

  • Dies ist zwar interessant, aber für die Antwort nicht wirklich wichtig. Selbst wenn strcmp in beiden Fällen aufgerufen würde, wäre es vollkommen gültig, unterschiedliche Werte für dieselbe Eingabezeichenfolge zurückzugeben (solange die Rückgabewerte beide das gleiche Vorzeichen haben usw.).

    – davmac

    3. Januar ’15 um 2:53

  • @davmac, anscheinend wollte das OP wissen, warum die Werte unterschiedlich sind (obwohl beide negativ sind)

    – asimes

    3. Januar ’15 um 2:56

  • @asimes mein Punkt ist, dass dies nur ein Teil der Erklärung dafür ist, warum sie unterschiedlich sind. Oder, wenn Sie es vorziehen, ist dies eine Erklärung dafür, warum sie unterschiedlich sein könnten (denken Sie daran, dass unterschiedliche Compiler, Plattformen usw. unterschiedliche Ergebnisse liefern können). Aber die Frage impliziert, dass das OP nicht versteht, warum sie kann unterschiedlich sein und es wäre falsch anzunehmen, dass das numerische Ergebnis für die gleichen Eingabezeichenfolgen immer gleich sein muss.

    – davmac

    3. Januar ’15 um 3:01


  • @davmac Es wäre erlaubt, dass sie anders sind, aber überraschend und unlogisch. Außer wenn Sie so etwas wie den “Bastard Compiler From Hell”™ haben…

    – glglgl

    3. Januar ’15 um 10:50

  • Ich glaube, es wird auch erwähnt, dass es ein sein sollte unsignierter Vergleich so dass ein erweiterter (negativer) ASCII-Wert größer ist als ein Standard-Ascii-Wert

    – Technosaurus

    3. Januar ’15 um 21:25

1642023245 464 Inkonsistenter strcmp Ruckgabewert bei der Ubergabe von Strings als Zeiger oder
davmac

Ich denke, Sie glauben, dass der von zurückgegebene Wert strcmp sollte irgendwie von den Eingabestrings abhängen, die ihm auf eine Weise übergeben werden, die nicht durch die Funktionsspezifikation definiert ist. Das ist nicht richtig. Siehe zum Beispiel die POSIX-Definition:

http://pubs.opengroup.org/onlinepubs/009695399/functions/strcmp.html

Nach Abschluss soll strcmp() eine ganze Zahl größer, gleich oder kleiner als 0 zurückgeben, wenn der String, auf den s1 zeigt, größer, gleich oder kleiner ist als der String, auf den s2 zeigt.

Genau das sehen Sie. Die Implementierung muss keine Garantie über die genau Rückgabewert – nur der kleiner als null, gleich null oder größer als null ist.

  • Also gibt es dann eine zufällige negative Zahl zurück? Ich denke, es sollte sowieso deterministisch sein, und es sollte eine Erklärung für das beobachtete Verhalten geben.

    – Iharob Al Asimi

    3. Januar ’15 um 3:48

  • @iharob : Es ist nicht “zufällig”, im zweiten Fall ist es das Ergebnis von ‘f’ – ‘a’, aber das ist selbst das Ergebnis des Spezifischen strcmp() (obwohl ich bezweifle, dass sich die Implementierungen in dieser Hinsicht unterscheiden). Das erste Ergebnis wird durch die Antwort von Shafic erklärt und ist vom Compiler (oder der Compileroption) abhängig. In jedem Fall können Sie sich auf kein anderes Ergebnis verlassen als das, das durch die Standardspezifikation der Funktion garantiert wird.

    – Clifford

    3. Januar ’15 bei 3:56


  • @iharob: Die Rückgabe einer zufälligen negativen Zahl würde zwar die Spezifikation erfüllen, aber das passiert hier nicht. Die “Erklärung für das beobachtete Verhalten” ist, dass die strcmp Implementierung(en) haben bei verschiedenen Gelegenheiten unterschiedliche Werte zurückgegeben – mit anderen Worten, das beobachtete Verhalten hängt von der Implementierung der Funktion ab. Wir könnten verschiedene Gründe untersuchen, warum eine Implementierung unterschiedliche numerische Ergebnisse liefern könnte (siehe Shafiks Antwort), aber ich persönlich denke, der wichtigste Punkt ist, “keine Annahmen über das Verhalten zu treffen, die in der Spezifikation nicht explizit sind”.

    – davmac

    3. Januar ’15 um 5:27

.

477470cookie-checkInkonsistenter strcmp()-Rückgabewert bei der Übergabe von Strings als Zeiger oder als Literale

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

Privacy policy