Embedded C-Compiler ermöglichen void main (), da möglicherweise kein Betriebssystem vorhanden ist, dem ein Rückkehrcode zugewiesen werden kann.
Jeanne Pindar
26
Wie kann eine solche Frage so oft bewertet werden? Es ist wirklich nicht so interessant ... Ich meine, dass Strings Arrays und Arrays Zeiger sind, ist wirklich ein alter Hut in C, nicht wahr?
Felix Dombek
64
@Felix, es ist eine präzise geschriebene Frage, die einen häufigen Verwirrungspunkt für Sprachanfänger anspricht. SO ist nicht nur für Experten gedacht, sondern auch für Anfänger, und gezielte Fragen wie diese sind gut, um Anfänger in Zukunft darauf hinzuweisen.
Bdonlan
37
@ Felix: Du liegst falsch. Arrays sind keine Zeiger
John Dibling
Antworten:
209
Was Sie vergleichen, sind die beiden Speicheradressen für die verschiedenen Zeichenfolgen, die an verschiedenen Orten gespeichert sind. Dies sieht im Wesentlichen so aus:
if(0x00403064==0x002D316A)// Two memory locations{
printf("Yes, equal");}
Verwenden Sie den folgenden Code, um zwei Zeichenfolgenwerte zu vergleichen:
"a" == "a"Abhängig von Ihrem Compiler, der zur Kompilierungszeit gleiche Zeichenfolgen zu einer kombinieren kann , kann dies tatsächlich true zurückgeben, um Platz zu sparen.
Wenn Sie zwei Zeichenwerte (die keine Zeiger sind) vergleichen, handelt es sich um einen numerischen Vergleich. Beispielsweise:
GCC hat auch die Optionen -fmerge-constantsund -fno-merge-constantsaktivieren / deaktivieren String und Floating-Point - Konstante über Übersetzungseinheiten verschmelzen, obwohl auf einigen GCCs scheint es , dass konstante Verschmelzung immer aktiviert , unabhängig von dieser Option.
Adam Rosenfield
2
Es würde funktionieren, wenn Sie 'a' anstelle von "a" verwenden. Das erste ist ein Zeichen, das eigentlich ein numerischer Wert ist.
GolezTrol
@GolezTrol: In C hat das Literal 'a' tatsächlich den intTyp. :-) Außerdem müssen Zeiger keine numerischen Werte sein.
Bastien Léonard
intist auch numerisch, nicht wahr? Aber ich dachte, Zeichen wären Byte. Int ist 4 Bytes. Die Zeiger selbst sind ebenfalls ganzzahlig. Sie enthalten die Adresse einer Reihe von Daten (Daten, die tatsächlich nicht numerisch sein müssen).
GolezTrol
'a' == 'A' // not true... MySQL unterscheidet sich.
Steven
52
Ich bin etwas spät zur Party, aber ich werde trotzdem antworten. technisch die gleichen Bits, aber aus einer etwas anderen Perspektive (C-Sprache unten):
In C bezeichnet der Ausdruck "a"ein Zeichenfolgenliteral , bei dem es sich um ein statisches unbenanntes Array const charmit einer Länge von zwei handelt. Das Array besteht aus Zeichen, 'a'und '\0'das abschließende Nullzeichen signalisiert das Ende der Zeichenfolge.
In C gibt es jedoch auf die gleiche Weise, wie Sie Arrays nicht nach Wert an Funktionen übergeben oder ihnen Werte zuweisen können ( nach der Initialisierung ), keinen überladenen Operator ==für Arrays, sodass es nicht möglich ist, sie direkt zu vergleichen. Erwägen
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 das ==Arrays nicht vergleicht, was macht es dann tatsächlich? In C zerfallen Arrays in fast allen Kontexten - einschließlich dieses - in Zeiger (die auf das erste Element des Arrays zeigen) - und der Vergleich von Zeigern auf Gleichheit bewirkt, was Sie erwarten. So effektiv, wenn Sie das tun
"a"=="a"
Sie vergleichen tatsächlich die Adressen der ersten Zeichen in zwei unbenannten Arrays . Gemäß dem C-Standard kann der Vergleich entweder wahr oder falsch ergeben (dh 1 oder 0) - "a"s können tatsächlich dasselbe Array oder zwei völlig unabhängige Arrays bezeichnen. In technischer Hinsicht ist der resultierende Wert nicht angegeben , was bedeutet, dass der Vergleich zulässig ist (dh es ist kein undefiniertes Verhalten oder ein Syntaxfehler), aber jeder Wert ist gültig und die Implementierung (Ihr Compiler) ist nicht erforderlich, um zu dokumentieren, was tatsächlich passieren wird.
Wie andere bereits betont haben, verwenden Sie zum Vergleichen von "c-Zeichenfolgen" (dh Zeichenfolgen, die mit einem Nullzeichen abgeschlossen sind) strcmpdie in der Standard-Header-Datei enthaltene Komfortfunktion string.h. Die Funktion hat einen Rückgabewert von 0für gleiche Zeichenfolgen. Es wird als bewährte Methode angesehen, den Rückgabewert explizit mit zu vergleichen, 0anstatt den Operator `! ´ zu verwenden, d. h
strcmp(str1, str2)==0// instead of !strcmp(str1, str2)
Es ist nicht spezifiziert, ob diese Arrays unterschiedlich sind, vorausgesetzt, ihre Elemente haben die entsprechenden Werte .
In diesem Fall ist also nicht spezifiziert, ob beide "a"s verschieden sind. Ein optimierter Compiler könnte eine einzelne "a"an der schreibgeschützten Stelle behalten, und beide Referenzen könnten darauf verweisen.
Da es sich um zwei separate const char*Zeiger handelt, keine tatsächlichen Werte. Sie sagen so etwas wie das, 0x019181217 == 0x0089178216was natürlich NEIN zurückgibt
String-Literale sind keine Zeiger, sondern Arrays. Beim Vergleich verfallen sie jedoch zu Zeigern.
GManNickG
@ Gman wahr, tut mir leid, dass ich nicht wirklich klar darüber bin, neige dazu, es zu vergessen :)
Antwan van Houdt
9
Einfach ausgedrückt hat C keinen eingebauten String-Vergleichsoperator. Auf diese Weise können Zeichenfolgen nicht verglichen werden.
Stattdessen werden Zeichenfolgen mithilfe von 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. In Ihrem Beispiel werden die Zeiger verglichen, und anscheinend sind Ihre beiden Versionen der Zeichenfolge an unterschiedlichen Adressen vorhanden.
Aber es geht nicht darum, die Saiten selbst zu vergleichen, wie Sie zu erwarten scheinen.
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 verstehe "a"=="a"-2. Naja...
Warum sollten Sie erwarten, dass Zeichenfolgen an der 4-Byte-Grenze ausgerichtet werden? Sie sind keine Ints. 2 ist das, was ich erwarten würde (wenn der Compiler sie nicht zusammenführt), da jede Zeichenfolge zwei Bytes lang ist, einschließlich des Null-Terminators.
Sergei Tachenov
Ein gewisser Grad an Ausrichtung kann beispielsweise die gleichzeitige strcmpAusführung mehrerer Bytes ermöglichen. Einige Compiler tun es, andere nicht, andere nur für Strings, die länger als ein Minimum sind ...
zwol
@Zack: Wie würden sie die Länge der Zeichenfolge kennen, bevor sie sie tatsächlich vergleichen?
Joachim Sauer
Ich meinte, einige Compiler richten Strings länger als ein Minimum aus.
zwol
1
Sie vergleichen zwei Speicheradressen, sodass das Ergebnis nicht immer wahr ist. Hast du es versucht if('a' == 'a'){...}?
Zeichen belegen nur 1 Byte, aber Zeichenliterale wie z. B. 'a'sind tatsächlich Ganzzahlen.
Spidey
0
Einige Compiler verfügen über die Option "Zeichenfolgen zusammenführen", mit der Sie erzwingen können, dass alle konstanten Zeichenfolgen dieselbe Adresse haben. Wenn Sie das nutzen "a" == "a"würden , wäre true.
" und es sollte wahr sein " - Nein. Es ist nicht angegeben, ob die Zeichenfolgenliterale am selben Speicherort gespeichert werden. Lesen Sie die anderen Antworten.
void main
??? Ew ...Antworten:
Was Sie vergleichen, sind die beiden Speicheradressen für die verschiedenen Zeichenfolgen, die an verschiedenen Orten gespeichert sind. Dies sieht im Wesentlichen so aus:
Verwenden Sie den folgenden Code, um zwei Zeichenfolgenwerte zu vergleichen:
"a" == "a"
Abhängig von Ihrem Compiler, der zur Kompilierungszeit gleiche Zeichenfolgen zu einer kombinieren kann , kann dies tatsächlich true zurückgeben, um Platz zu sparen.Wenn Sie zwei Zeichenwerte (die keine Zeiger sind) vergleichen, handelt es sich um einen numerischen Vergleich. Beispielsweise:
quelle
-fmerge-constants
und-fno-merge-constants
aktivieren / deaktivieren String und Floating-Point - Konstante über Übersetzungseinheiten verschmelzen, obwohl auf einigen GCCs scheint es , dass konstante Verschmelzung immer aktiviert , unabhängig von dieser Option.int
Typ. :-) Außerdem müssen Zeiger keine numerischen Werte sein.int
ist auch numerisch, nicht wahr? Aber ich dachte, Zeichen wären Byte. Int ist 4 Bytes. Die Zeiger selbst sind ebenfalls ganzzahlig. Sie enthalten die Adresse einer Reihe von Daten (Daten, die tatsächlich nicht numerisch sein müssen).'a' == 'A' // not true
... MySQL unterscheidet sich.Ich bin etwas spät zur Party, aber ich werde trotzdem antworten. technisch die gleichen Bits, aber aus einer etwas anderen Perspektive (C-Sprache unten):
In C bezeichnet der Ausdruck
"a"
ein Zeichenfolgenliteral , bei dem es sich um ein statisches unbenanntes Arrayconst char
mit einer Länge von zwei handelt. Das Array besteht aus Zeichen,'a'
und'\0'
das abschließende Nullzeichen signalisiert das Ende der Zeichenfolge.In C gibt es jedoch auf die gleiche Weise, wie Sie Arrays nicht nach Wert an Funktionen übergeben oder ihnen Werte zuweisen können ( nach der Initialisierung ), keinen überladenen Operator
==
für Arrays, sodass es nicht möglich ist, sie direkt zu vergleichen. ErwägenWenn das
==
Arrays nicht vergleicht, was macht es dann tatsächlich? In C zerfallen Arrays in fast allen Kontexten - einschließlich dieses - in Zeiger (die auf das erste Element des Arrays zeigen) - und der Vergleich von Zeigern auf Gleichheit bewirkt, was Sie erwarten. So effektiv, wenn Sie das tunSie vergleichen tatsächlich die Adressen der ersten Zeichen in zwei unbenannten Arrays . Gemäß dem C-Standard kann der Vergleich entweder wahr oder falsch ergeben (dh 1 oder 0) -
"a"
s können tatsächlich dasselbe Array oder zwei völlig unabhängige Arrays bezeichnen. In technischer Hinsicht ist der resultierende Wert nicht angegeben , was bedeutet, dass der Vergleich zulässig ist (dh es ist kein undefiniertes Verhalten oder ein Syntaxfehler), aber jeder Wert ist gültig und die Implementierung (Ihr Compiler) ist nicht erforderlich, um zu dokumentieren, was tatsächlich passieren wird.Wie andere bereits betont haben, verwenden Sie zum Vergleichen von "c-Zeichenfolgen" (dh Zeichenfolgen, die mit einem Nullzeichen abgeschlossen sind)
strcmp
die in der Standard-Header-Datei enthaltene Komfortfunktionstring.h
. Die Funktion hat einen Rückgabewert von0
für gleiche Zeichenfolgen. Es wird als bewährte Methode angesehen, den Rückgabewert explizit mit zu vergleichen,0
anstatt den Operator `! ´ zu verwenden, d. hquelle
Gemäß C99 (Abschnitt 6.4.5 / 6)
In diesem Fall ist also nicht spezifiziert, ob beide
"a"
s verschieden sind. Ein optimierter Compiler könnte eine einzelne"a"
an der schreibgeschützten Stelle behalten, und beide Referenzen könnten darauf verweisen.Überprüfen Sie die Ausgabe auf gcc hier
quelle
Da es sich um zwei separate
const char*
Zeiger handelt, keine tatsächlichen Werte. Sie sagen so etwas wie das,0x019181217 == 0x0089178216
was natürlich NEIN zurückgibtVerwenden Sie
strcmp()
anstelle von==
quelle
Einfach ausgedrückt hat C keinen eingebauten String-Vergleichsoperator. Auf diese Weise können Zeichenfolgen nicht verglichen werden.
Stattdessen werden Zeichenfolgen mithilfe von 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. In Ihrem Beispiel werden die Zeiger verglichen, und anscheinend sind Ihre beiden Versionen der Zeichenfolge an unterschiedlichen Adressen vorhanden.
Aber es geht nicht darum, die Saiten selbst zu vergleichen, wie Sie zu erwarten scheinen.
quelle
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 verstehe"a"=="a"-2
. Naja...quelle
strcmp
Ausführung mehrerer Bytes ermöglichen. Einige Compiler tun es, andere nicht, andere nur für Strings, die länger als ein Minimum sind ...Sie vergleichen zwei Speicheradressen, sodass das Ergebnis nicht immer wahr ist. Hast du es versucht
if('a' == 'a'){...}
?quelle
Diese Frage ist für alle Anfänger eine sehr gute Erklärung.
Lassen Sie mich auch dazu beitragen.
Wie alle oben erklärt haben, warum Sie eine solche Ausgabe erhalten.
Jetzt, wenn du deinen Prog willst. Dann "Ja gleich" drucken
entweder verwenden
oder verwenden
Sie nicht "a" als Zeichenfolgen, verwenden Sie sie als Zeichen ....
in C Zeichen sind 1 Byte kurze Ganzzahl .......
quelle
'a'
sind tatsächlich Ganzzahlen.Einige Compiler verfügen über die Option "Zeichenfolgen zusammenführen", mit der Sie erzwingen können, dass alle konstanten Zeichenfolgen dieselbe Adresse haben. Wenn Sie das nutzen
"a" == "a"
würden , wäretrue
.quelle
wenn der Vergleich zwischen Zeichen immer in einfachen Anführungszeichen steht, z
und C kann den String-Vergleich nicht unterstützen
"abc" == "abc"
Es ist erledigt mit
strcmp("abc","abc")
quelle
Dieser Typ verwendet keine Variablen. Stattdessen verwendet er vorübergehend Textarrays:
a
unda
. Der Grund warumfunktioniert natürlich nicht, ist, dass man keine variablen vergleicht.
Wenn Sie Variablen erstellen würden wie:
dann könnte man vergleichen
text
mittext2
, und es sollte wahrVielleicht solltest du nicht vergessen zu verwenden
{
und}
=)quelle