Diese Implementierung ist ungültig, da sie undefiniertes Verhalten enthält.
Die Erklärung kommt aus dem Abschnitt 6.5, Absatz 2 der Norm:
Zwischen dem vorherigen und nächsten sequence point ein Objekt hat seinen gespeicherten Wert geändert höchstens einmal durch die Auswertung eines Ausdrucks haben. Außerdem darf der vorherige Wert nur gelesen werden, um den zu speichernden Wert zu bestimmen.
Der Standard gibt ein Beispiel für einen Ausdruck, nicht definiertes Verhalten betrachtet wird, um den zweiten Satz zu klären:
a[i++] = i;
In diesem Ausdruck wird der Wert von i
gelesen wird nicht nur den neuen Wert zu bestimmen zu sein gespeichert, sondern auch um den Speicherort eines anderen Werts zu bestimmen.
Dies ist genau das, was in Ihrem Ausdruck geschieht:
*str++ = toupper(*str);
Der einzige Unterschied ist, dass Ihr Ausdruck Zeiger verwendet, und ruft toupper
dazwischen.
Diese Anforderung mag willkürlich erscheinen, hat aber einen Grund. Der C-Standard ermöglicht es dem Compiler, vor oder nach dem Aufruf von toupper
sichtbare Effekte von ++
sichtbar zu machen, um Compilerschreibern maximale Flexibilität zu ermöglichen. Ohne eine Beschränkung auf die Verwendung von str
in Ausdruck könnte dies zu unterschiedlichem Verhalten auf verschiedenen Plattformen führen, so dass die Standardautoren entschieden haben, es direkt zu verbieten.
Sie geben nichts von einer Funktion mit einem Rückgabewert zurück, und Sie sollten wirklich viel genauer darüber sein, was nicht funktioniert und so weiter. "Nicht arbeiten" ist selten eine nützliche Beschreibung. –
Sie sollten es in einem Debugger durchlaufen. – JJF
Warnung dienen einem Zweck. Achte auf sie! – Olaf