‘\0’ wertet falsch aus, “\0” wertet wahr aus

Lesezeit: 6 Minuten

Rahns Benutzeravatar
Rahn

Inspiriert von einem Programm beschrieben in K&R Abschnitt 5.5:

void strcpy(char *s, char *t)
{
    while(*s++ = *t++);
}

C-Programm

if ('\0') { printf("\'\\0\' -> true \n"); }
else      { printf("\'\\0\' -> false\n"); }

if ("\0") { printf("\"\\0\" -> true \n"); }
else      { printf("\"\\0\" -> false\n"); }

Drucke

'\0' -> false
"\0" -> true

Warum machen '\0' und "\0" in C anders auswerten?

Clang-Version 3.8.0

  • Die erste ist die Nullzeichendas zweite ist leerer String.

    – David C. Rankin

    30. April 2016 um 5:26 Uhr

  • weil sie verschiedene Dinge sind, warum sollten sie identisch bewertet werden?

    – njzk2

    1. Mai 2016 um 0:54 Uhr

  • Und warum vergleichst du Zeichenfolgen/Zeichen mit booleschen Werten?

    – Leichtigkeitsrennen im Orbit

    1. Mai 2016 um 11:30 Uhr

  • @LightnessRacesinOrbit Ein Programm, beschrieben in K&R die den Inhalt eines Zeichens kopieren[] zum anderen: while((dest[i++] = source[i++]));. Nicht klar erinnert, werde ich morgen überprüfen.

    – Rahn

    1. Mai 2016 um 16:34 Uhr

  • aus dem gleichen Grund ist “false” wahr.

    – Matija Nalis

    30. Januar 2017 um 12:09 Uhr

Benutzeravatar von user253751
Benutzer253751

Erinnern Sie sich, wie String-Literale in C funktionieren – "\0" ist ein Zeichen-Array, das zwei Null-Bytes enthält (das von Ihnen angeforderte und das implizite am Ende). Bei der Auswertung für die if test, zerfällt es in einen Zeiger auf sein erstes Zeichen. Dieser Zeiger ist nicht NULL, daher wird er als wahr betrachtet, wenn er als Bedingung verwendet wird.

'\0' ist die Zahl Null, gleichbedeutend mit gerade 0. Es ist eine ganze Zahl, die Null ist, daher wird sie als falsch angesehen, wenn sie als Bedingung verwendet wird.

  • @MM: Es ist ein String-Literal;)

    – Strickl

    30. April 2016 um 8:24 Uhr

  • Ja, String-Literale sind Arrays von char

    – MM

    30. April 2016 um 8:39 Uhr

  • Dies “"\0" ist ein Zeiger auf ein Zeichenarray” passt nicht gut zu einer mit 28 ++ bewerteten Antwort, da sie in zweierlei Hinsicht einfach falsch ist. "\0" s kein Zeiger, sondern ein Array, und wenn dieses Array aus welchen Gründen auch immer zu einem Zeiger zerfallen würde, würde es nicht auf das Array zeigen, sondern auf sein 1. Element.

    – alk

    30. April 2016 um 12:02 Uhr


  • @MrLister Zeiger auf ein Array und Zeiger auf ein Element eines Arrays sind zwei verschiedene Bestien.

    – Spikatrix

    30. April 2016 um 15:12 Uhr

  • @MrLister char (*ptr)[] = &"test"; wäre ein Zeiger auf das Zeichenfolgenliteral while char* ptr = "test"; wäre ein Zeiger auf die Adresse des ersten Zeichens des String-Literals "test".

    – Spikatrix

    30. April 2016 um 15:20 Uhr

Benutzeravatar von Spikatrix
Spikatrix

Zuallererst müssen Sie bedenken, dass in C,

  • Null ist falsch und Nicht-Null ist wahr.
  • Für Zeigertypen, NULL ist falsch und nichtNULL ist wahr.

'\0'wie andere gesagt haben, ist dasselbe wie das Integer-Literal 0 und ist daher falsch (siehe erster Aufzählungspunkt oben, um zu erfahren, warum).

"\0" ist ein Zeichenfolgenliteral, das zwei enthält \0 Zeichen (eines, das Sie explizit hinzugefügt haben, und das andere, das implizit ist und vom Compiler hinzugefügt wird). Das Zeichenfolgenliteral wird irgendwo im Nur-Lese-Speicher gespeichert. Wenn Sie verwenden "\0"wird es in einen Zeiger auf sein erstes Element konvertiert. Dies wird allgemein als “Array-Zerfall” bezeichnet. (Das ist der Grund, warum Sachen wie char* str = "string"; funktioniert).

So, Sie überprüfen effektiv die Adresse des ersten Zeichens des Zeichenfolgenliterals. Da die Adresse des String-Literals immer non-NULLdas if wird immer wahr sein (siehe zweiter Aufzählungspunkt oben, um zu wissen, warum).


: Dieser “Verfall” von Arrays tritt nicht immer auf. Siehe Ausnahme für ein Array, das nicht in einen Zeiger zerfällt?

  • Sie haben natürlich Recht, dass der Wert 0 falsch ist. Ein Zeichen ist jedoch nicht unbedingt dasselbe wie eine ganze Zahl. Ein int ist immer signiert, es sei denn, Sie geben explizit unsigned an. Ob ein Zeichen signiert ist oder nicht, ist implementierungsabhängig!

    – Herr Lister

    30. April 2016 um 15:08 Uhr

  • '\0' ist ein intIIRC, obwohl es sieht aus wie ein char.

    – Spikatrix

    30. April 2016 um 15:12 Uhr

  • Außerdem bin ich mir nicht sicher, wie unsigned und signed ist hier relevant. Ich meine unsigned oder signed, char oder intalle können 0 darstellen.

    – Spikatrix

    30. April 2016 um 15:15 Uhr


  • Was das Problem mit dem (IMHO zu häufigen) Kurzschrifttest für 0/NULL zeigt. Wenn das OP zB “if (“\0” == NULL) geschrieben hätte, wäre es ziemlich offensichtlich, was das Problem war.

    – jamesqf

    30. April 2016 um 18:11 Uhr

  • Nur eine Notiz, '\0' wäre char in C++, obwohl es ist int in C.

    – Ruslan

    1. Mai 2016 um 11:24 Uhr

Benutzeravatar von FedeWar
FedeWar

'\0' ist eine Zahl: 0also wird es als falsch ausgewertet (0 = falsch, !0 = wahr).

Aber "\0" ist ein Zeiger auf einen schreibgeschützten Abschnitt, in dem die eigentliche Zeichenfolge gespeichert ist, der Zeiger ist es nicht NULL ergo es stimmt.

  • "\0" ist kein Zeiger. Es ist ein String-Literal, dessen Wert ein Array ist (das in den meisten, aber nicht allen Kontexten implizit in einen Zeiger umgewandelt wird).

    – Keith Thompson

    6. Mai 2016 um 21:56 Uhr

Benutzeravatar von Fluter
flattern

Betrachtet man zunächst die beiden Bedingungen, '\0' ist eine Konstante vom Typ Integer, die das Nullzeichen C bezeichnet, was dasselbe ist wie 0. Während "\0" ist ein Zeichenfolgenliteral, das 2 Bytes enthält, das angegebene und das implizit hinzugefügte Null-Abschlussbyte. Da der Zeiger ein Zeichenfolgenliteral ist, kann dies nicht der Fall sein NULL.

Zweitens, in C, für die Bedingung von if -Anweisung wird alles, was nicht Null ist, als ausgewertet trueund Null wird ausgewertet als false.

Nach dieser Regel wird es klar sein '\0' ist falseund "\0" bewertet als true.

Benutzeravatar von Bora
Bora

Beachten Sie zunächst, dass der Hexadezimalwert False ist 0x00 und True ist ein beliebiger anderer Wert als 0x00.

"\0" ist eine Zeichenfolge mit einem Zeichen und einem Null-Terminator '\0' Am Ende. Es ist also ein Zeichenzeiger, der auf ein Array von 2 Bytes zeigt: ['\0', '\0']. In diesem Array ist das erste das Zeichen und das andere der Nullterminator.

Nach dem Kompilieren (ohne Optimierung) wird dieser Zeichenzeiger vorübergehend einer Adresse im Speicher zugewiesen, die auf das erste Byte dieser zwei Bytes zeigt. Diese Adresse könnte z. 0x18A6 in hexadezimal. Der Compiler (die meisten von ihnen) schreibt diese beiden Werte also tatsächlich in den Speicher. Da ein String eigentlich die Adresse des ersten Bytes dieses Strings ist, wird unser Ausdruck interpretiert als 0x18A6 != false . Es ist also klar 0x18A6 != 0x00 ist wahr.

'\0' ist einfach 0x00 in hexadezimal. 0x00 != 0x00 ist falsch.

Diese Antwort ist für eine 8-Bit-Datenarchitektur mit 16-Bit-Adressierung geschrieben. Ich hoffe das hilft.

‘\0’ ist ein Null Zeichen, das den Wert von hat 0. Es wird verwendet, um eine Zeichenkette abzuschließen. Also gilt es als falsch.

“\0” ist ein Null oder leer Schnur. Das einzige Zeichen in der Zeichenfolge ist das Nullzeichen, das die Zeichenfolge beendet. Daher wird es als wahr betrachtet.

Benutzeravatar von G.Mather
G. Mather

‘\0’ ist ein Zeichen, das gleich der Zahl Null ist. “\0” ist ein String und wir fügen normalerweise ‘\0’ am Ende eines Strings hinzu. Verwenden Sie ‘\0’ oder ‘\0’ nicht in bedingten Anweisungen, da dies ziemlich verwirrend ist.

Folgende Verwendung wird vorgeschlagen:

if (array[0] != 0)
{

}

if (p != 0)
{

}

if (p != NULL)
{

}

  • Ich würde immer lieber sehen '\0' wird in Bedingungen verwendet, da es anzeigt, dass Sie das ‘Ding’ als Zeichenfolge und nicht als Array von Zahlen behandeln.

    – Atti

    21. März 2017 um 13:23 Uhr

1412450cookie-check‘\0’ wertet falsch aus, “\0” wertet wahr aus

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

Privacy policy