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?
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).
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.
.
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önnenstrcmp(a,b) == strcmp(c,d)
wahr ist, wenn beide Vergleiche null ergeben.– David Hammen
3. Januar ’15 bei 3:42