Warum ist “a” != “a” in C?

Lesezeit: 5 Minuten

Benutzeravatar von Javed Akram
Javed Akram

void main() {
    if("a" == "a")
      printf("Yes, equal");  
    else
      printf("No, not equal");
}

Warum ist die Ausgabe No, not equal?

  • void main ??? Äh…

    – PaulR

    30. Januar 2011 um 15:59 Uhr

  • Eingebettete C-Compiler erlauben void main(), da es möglicherweise kein Betriebssystem gibt, dem ein Rückgabecode übergeben werden kann.

    – Jeanne Pindar

    30. Januar 2011 um 20:20 Uhr

  • Wie kann eine Frage wie diese so oft positiv bewertet werden? Es ist wirklich nicht so interessant … Ich meine, dass Strings Arrays und Arrays Zeiger sind, ist wirklich ein alter Hut in C, oder?

    – Felix Dombek

    31. Januar 2011 um 2:27 Uhr


  • @Felix, es ist eine prägnant geschriebene Frage, die einen häufigen Verwirrungspunkt für Neulinge in der Sprache anspricht. SO ist nicht nur etwas für Experten, sondern auch für Anfänger, und gezielte Fragen wie diese sind gut, um Anfänger in Zukunft darauf hinzuweisen.

    – bdonlan

    31. Januar 2011 um 3:00 Uhr

  • @Felix: Du liegst falsch. Arrays sind keine Zeiger

    – Johannes Dibling

    31. Januar 2011 um 20:52 Uhr

Benutzeravatar von Tim Cooper
Tim Cooper

Was Sie vergleichen, sind die beiden Speicheradressen für die verschiedenen Zeichenfolgen, die an verschiedenen Orten gespeichert sind. Das sieht im Wesentlichen so aus:

if(0x00403064 == 0x002D316A) // Two memory locations
{
    printf("Yes, equal");
}

Verwenden Sie den folgenden Code, um zwei Zeichenfolgenwerte zu vergleichen:

#include <string.h>

...

if(strcmp("a", "a") == 0)
{
    // Equal
}

Zusätzlich, "a" == "a" kann tatsächlich true zurückgeben, abhängig von Ihrem Compiler, der gleiche Strings zur Kompilierzeit zu einem kombinieren kann, um Platz zu sparen.

Wenn Sie zwei Zeichenwerte vergleichen (die keine Zeiger sind), handelt es sich um einen numerischen Vergleich. Zum Beispiel:

'a' == 'a' // always true

  • GCC hat auch die Optionen -fmerge-constants und -fno-merge-constants um das konstante Zusammenführen von Zeichenfolgen und Fließkommazahlen über Übersetzungseinheiten hinweg zu aktivieren/deaktivieren, obwohl es auf einigen GCCs scheint, dass das konstante Zusammenführen unabhängig von dieser Option immer aktiviert ist.

    – Adam Rosenfield

    30. Januar 2011 um 15:35 Uhr

  • Es würde funktionieren, wenn Sie ‘a’ anstelle von ‘a’ verwenden. Das erste ist ein Zeichen, das eigentlich ein numerischer Wert ist.

    – GolezTrol

    30. Januar 2011 um 15:41 Uhr

  • @GolezTrol: In C hat das wörtliche ‘a’ tatsächlich int Typ. 🙂 Außerdem müssen Zeiger keine numerischen Werte sein.

    – Bastien Léonard

    30. Januar 2011 um 16:25 Uhr


  • int ist auch numerisch, oder? Aber ich dachte, Zeichen wären Byte. Ganzzahl ist 4 Byte. Zeiger selbst sind ebenfalls ganzzahlig. Sie enthalten die Adresse einer Reihe von Daten (Daten, die tatsächlich nicht numerisch sein müssen).

    – GolezTrol

    30. Januar 2011 um 16:58 Uhr

  • 'a' == 'A' // not true … MySQL ist anderer Meinung.

    – Stefan

    30. Januar 2011 um 21:09 Uhr


Benutzeravatar von eq-
gleich

Ich komme etwas spät zur Party, aber ich werde trotzdem antworten; technisch die gleichen Bits, aber von a bisschen andere Perspektive (C-Sprache unten):

In C ist der Ausdruck "a" bezeichnet a String-Literalbei dem es sich um ein statisches unbenanntes Array von handelt const charmit einer Länge von zwei – das Array besteht aus Zeichen 'a' und '\0' – Das abschließende Nullzeichen signalisiert das Ende der Zeichenkette.

In C können Sie jedoch auf die gleiche Weise Arrays nicht per Wert an Funktionen übergeben – oder ihnen Werte zuweisen (nach Initialisierung) – es gibt keinen überladenen Operator == für Arrays, daher ist es nicht möglich, sie direkt zu vergleichen. In Betracht ziehen

int a1[] = {1, 2, 3};
int a2[] = {3, 4, 5};
a1 == a2 // is this meaningful? Yes and no; it *does* compare the arrays for
         // "identity", but not for their values. In this case the result
         // is always false, because the arrays (a1 and a2) are distinct objects

Wenn die == vergleicht keine Arrays, was macht es dann eigentlich? In C, in fast allen Kontexten – einschließlich diesem – Arrays Verfall in Zeiger (die auf das erste Element des Arrays zeigen) – und der Vergleich von Zeigern auf Gleichheit macht das, was Sie erwarten würden. So effektiv, wenn Sie dies tun

"a" == "a"

du bist es tatsächlich Vergleichen der Adressen der ersten Zeichen in zwei unbenannten Arrays. Nach dem C-Standard kann der Vergleich entweder wahr oder falsch (dh 1 oder 0) ergeben – "a"s kann tatsächlich dasselbe Array oder zwei völlig unabhängige Arrays bezeichnen. Technisch gesehen ist der resultierende Wert nicht spezifiziertwas bedeutet, dass der Vergleich zulässig ist (dh nicht undefiniertes Verhalten oder ein Syntaxfehler), aber jeder Wert ist gültig und die Implementierung (Ihr Compiler) muss nicht dokumentieren, was tatsächlich passieren wird.

Wie andere bereits betont haben, verwenden Sie zum Vergleichen von “c-Strings” (dh Strings, die mit einem Nullzeichen enden) die Convenience-Funktion strcmp in Standard-Header-Datei gefunden string.h. Die Funktion hat einen Rückgabewert von 0 für gleiche Saiten; Es wird als bewährte Methode angesehen, den Rückgabewert explizit mit zu vergleichen 0 anstatt den Operator `!´ zu verwenden, dh

strcmp(str1, str2) == 0 // instead of !strcmp(str1, str2)

Benutzeravatar von Prasoon Saurav
Prasun Saurav

Gemäß C99 (Abschnitt 6.4.5/6)

Zeichenfolgenliterale

Es ist nicht angegeben, ob diese Arrays unterschiedlich sind, vorausgesetzt, ihre Elemente haben die entsprechenden Werte.

In diesem Fall ist also nicht spezifiziert, ob beides der Fall ist "a"s sind verschieden. Ein optimierter Compiler könnte einen behalten "a" am schreibgeschützten Ort und beide Referenzen könnten darauf verweisen.

Sehen Sie sich die Ausgabe auf gcc an hier

Benutzeravatar von Antwan van Houdt
Antwan van Houdt

Weil sie 2 getrennt sind const char*‘s, Zeiger, keine tatsächlichen Werte. Du sagst sowas wie 0x019181217 == 0x0089178216 was natürlich NEIN zurückgibt

Verwenden strcmp() Anstatt von ==

Benutzeravatar von Jonathan Wood
Jonathan Holz

Einfach ausgedrückt, C hat keinen eingebauten String-Vergleichsoperator. Strings können auf diese Weise nicht verglichen werden.

Stattdessen werden Zeichenfolgen mit Standardbibliotheksroutinen wie strcmp() oder durch Schreiben von Code zum Durchlaufen jedes Zeichens in der Zeichenfolge verglichen.

In C gibt eine Textzeichenfolge in doppelten Anführungszeichen einen Zeiger auf die Zeichenfolge zurück. Ihr Beispiel vergleicht die Zeiger, und anscheinend existieren Ihre beiden Versionen der Zeichenfolge an unterschiedlichen Adressen.

Aber es vergleicht nicht die Saiten selbst, wie Sie es zu erwarten scheinen.

Benutzeravatar von Lesmana
Lesmana

Zeiger.

Der Erste "a" ist ein Zeiger auf eine nullterminierte ASCII-Zeichenfolge.

Der Zweite "a" ist ein Zeiger auf eine andere nullterminierte ASCII-Zeichenfolge.

Wenn Sie einen 32-Bit-Compiler verwenden, würde ich erwarten "a"=="a"-4. Ich habe es gerade mit tcc/Win32 versucht, und ich bekomme "a"=="a"-2. Nun ja…

Kens Benutzeravatar
Ken

Sie vergleichen zwei Speicheradressen, daher ist das Ergebnis nicht immer wahr. Hast du versucht if('a' == 'a'){...}?

1422050cookie-checkWarum ist “a” != “a” in C?

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

Privacy policy