Wie die Vorrangstellung des C-Operators Ihren Code beschädigt (und wie Sie ihn beheben können)

11

Du schreibst, was du meinst. Der Compiler liest, was er will.

Wenn Sie jemals auf eine Zeile C-Code gestarrt haben und davon überzeugt waren, dass sie eine Sache tut, nur um dann zuzusehen, wie sie etwas ganz anderes tat, dann haben Sie den Vorrang des Operators kennengelernt. Es ist kein Fehler. Es ist ein Merkmal der Sprache, das selbst erfahrene Entwickler ärgert.

Nehmen Sie diese einfache Arithmetik:

x=5+3*6;

Im Matheunterricht heißt es zuerst addieren. C sagt nein. Multiplikation und Division stehen auf einer höheren Ebene als Addition und Subtraktion. Der Compiler multipliziert zunächst 3 mit 6. Dann addiert es 5. X erhält 23. Nicht 48. Sie haben gerade bei einem Quiz Punkte verloren. Oder schlimmer noch, eine Produktionsbereitstellung.

Die Verwirrung wird größer, wenn Sie Operatoren und Syntax vermischen.

Schauen Sie sich diese Erklärung an:

char *a[10];

Ist „a“ ein Zeiger auf ein Array mit 10 Zeichen? Oder ist es ein Array von 10 Zeigern auf Zeichen?

Ohne die spezifischen Vorrangregeln zu kennen, raten Sie. In C binden Klammern „[]“ enger als Zeiger „*“. Das ist also ein Array von 10 Zeigern auf Zeichen.

Dies ist wichtig, da C nicht wie Englisch analysiert wird. Es wird wie eine starre Hierarchie analysiert.

Sie können Code schreiben, der richtig aussieht, aber aufgrund der Priorität stillschweigend fehlschlägt.

Betrachten Sie Zeigerarithmetik gemischt mit Strukturzugriff.

*p.i = 10;

Dies funktioniert nicht wie erwartet. Der Punktoperator „.“ hat eine höhere Priorität als der Dereferenzierungsoperator „*“. Der Compiler versucht, auf Member „i“ des Objekts zuzugreifen, auf das „p“ zeigt, bevor er „p“ dereferenziert. Aber „p“ ist ein Zeiger, keine Struktur. Der Compiler erstickt. Oder schlimmer noch, es interpretiert den Speicher auf eine Weise, die Daten beschädigt.

Sie müssen das Problem erzwingen.

(*p).i = 10;

Klammern gewinnen. Stets.

Die Hierarchie der Operatoren

Kernighan und Ritchie, die Architekten von C, legten in ihrem klassischen Text den Vorrang dar. Die folgende Tabelle zeigt die Reihenfolge. Die oberste Linie ist am höchsten. Unten ist am niedrigsten.

  1. Klammern „()“ und Tiefstellung „[]“.
  2. Von links nach rechts.
  3. Unäre Operatoren „++“, „–“, „+“, „-“, „!“, „~“, „(Typ)“, „*“ (Dereferenzierung), „&“ (Adresse), „sizeof“.
  4. Von rechts nach links.
  5. Multiplikativ „*“, „/“, „%“.
  6. Von links nach rechts.
  7. Zusatz „+“, „-“.
  8. Von links nach rechts.
  9. Umschalt „<<“, „>>“.
  10. Von links nach rechts.
  11. Relational <, <=, >, >=
  12. Von links nach rechts.
  13. Gleichheit ==, !=
  14. Von links nach rechts.
  15. Bitweises UND &
  16. Von links nach rechts.
  17. Bitweises XOR ^