Der Wert von s++
ist der ursprüngliche Wert von s
, bevor das Inkrement zu einem nicht angegebenen Zeitpunkt vor dem nächsten Sequenzpunkt auftritt.
Daher *s++
und *(s++)
sind äquivalent: Beide dereferenzieren den ursprünglichen Wert von s
. Ein anderer äquivalenter Ausdruck ist *(0, s++)
und nicht für schwache Nerven wie dieser:0[s++]
Beachten Sie jedoch, dass Ihre Funktion type size_t
for i
und seinen Rückgabetyp verwenden sollte:
size_t str_len(const char *s) {
size_t i = 0;
while (*s++) {
i++;
}
/* s points after the null terminator */
return i;
}
Hier ist eine potenziell effizientere Version mit einem einzelnen Inkrement pro Schleife:
size_t str_len(const char *s) {
const char *s0 = s;
while (*s++) {
/* nothing */
}
return s - 1 - s0;
}
Für diejenigen, die sich über die seltsamen Ausdrücke im zweiten Absatz wundern:
0, s++
ist eine Instanz des Kommaoperators ,
, der seinen linken Teil und dann seinen rechten Teil, der seinen Wert ausmacht, auswertet. daher(0, s++)
ist äquivalent zu (s++)
.
0[s++]
ist äquivalent zu (s++)[0]
und *(0 + s++)
oder *(s++ + 0)
die vereinfachen als *(s++)
. Das Transponieren des Zeigers und der Indexausdrücke in []
Ausdrücken ist weder sehr häufig noch besonders nützlich, entspricht jedoch dem C-Standard.
, s++
und schlimme Dinge werden passieren:)
In diesem Beispiel
s
zeigt auf das'a'
in"a"
. Dann wird es inkrementiert undi
auch inkrementiert. Zeigen Sie nuns
auf den Nullterminator undi
ist1
. Also im nächsten Durchlauf durch die Schleife*(s++)
ist'\0'
(was ist0
), also endet die Schleife und der aktuelle Wert voni
(das ist)1
) wird zurückgegeben.Im Allgemeinen wird die Schleife für jedes Zeichen in der Zeichenfolge einmal ausgeführt und stoppt dann am Nullterminator. Auf diese Weise werden die Zeichen gezählt.
quelle
s
gehalten , bevor erhöht wird . Was Sie beschreiben, ist das Verhalten von++s
(das tatsächlich um eins unterzählt und UB aufruft, wenn eine leere Zeichenfolge übergeben wird).Es macht vollkommen Sinn:
Genau aus diesem Grund wird der Zeiger inkrementiert und nicht das Zeichen. Nehmen wir an
(*s)++
, in diesem Fall wird das Zeichen inkrementiert und nicht der Zeiger. Die Dereferenzierung bedeutet, dass Sie jetzt mit dem Wert arbeiten, auf den sich der Zeiger bezieht, und nicht mit dem Zeiger selbst.Da beide Operatoren die gleiche Priorität haben, aber die Assoziativität von rechts nach links, können Sie
*s++
den Zeiger sogar einfach ohne Klammern inkrementieren.quelle
Der Post-Inkrement-Operator erhöht den Wert des Operanden um 1, aber der Wert des Ausdrucks ist der ursprüngliche Wert des Operanden vor der Inkrement-Operation.
Angenommen, das übergebene Argument
str_len()
ist"a"
. Instr_len()
zeigt der Zeigers
auf das erste Zeichen der Zeichenfolge"a"
. In demwhile
Schleife:Das
s
wird zwar inkrementiert, aber der Wert vons
im Ausdruck ist ein Zeiger auf das Zeichen, auf das er vor dem Inkrement zeigt, das ein Zeiger auf das erste Zeichen ist'a'
. Wenn der Zeigers
dereferenziert wird, gibt er Zeichen'a'
. In der nächsten Iteration zeigt ders
Zeiger auf das nächste Zeichen, das das Nullzeichen ist\0
. Wenns
dereferenziert wird, gibt es0
und die Schleife wird beendet. Beachten Sie, dasss
jetzt auf ein Element nach dem Nullzeichen der Zeichenfolge verwiesen wird"a"
.quelle