Die Ausgabe dieses C-Codes ist 49, aber kann mir jemand erklären, wie? [Duplikat]
#include <stdio.h>
#define CUBE(x) (x * x * x)
int main() {
printf("%d", CUBE(4+5));
return 0;
}
Antworten
Das Makro verwandelt den Code in:
printf("%d", (4+5 * 4+5 * 4+5));
das ist effektiv:
printf("%d", 4 + (5*4) + (5*4) + 5); // 29
Wenn Sie Würfel wollen 9
zu bekommen 729
, sollten Sie schreiben CUBE((4+5))
.
So wird das Makro während des Kompilierungsprozesses erweitert:
printf("%d", (4+5 * 4+5 * 4+5));
Da dieser Ausdruck *
eine höhere Priorität als hat +
, wird er als " (4 + (5 * 4) + (5 * 4) + 5)
produzierend" 49
anstatt als erwartet bewertet 729
.
Um solche Probleme mit der Priorität von Operatoren zu vermeiden, müssen alle Makroargumente in der Makrodefinition sowie im Ausdruck selbst in Klammern stehen:
#define CUBE(x) ((x) * (x) * (x))
Beachten Sie jedoch, dass diese Erweiterung von mehrfach CUBE
ausgewertet wird. Dies x
ist ein Problem, wenn das Makroargument Nebenwirkungen hat, wie z CUBE(i++)
.
Um all diese Probleme zu vermeiden, verwenden Sie eine Funktion und lassen Sie sie vom Compiler optimieren:
int cube(int x) {
return x * x * x;
}
Sie können static inline
vor dieser Funktionsdefinition hinzufügen , aber moderne Optimierer werden die Funktion ohne diese weiterhin einbinden.
Der C-Präprozessor ersetzt buchstäblich alle Instanzen von x durch 4 + 5, was zu folgendem Code führt:
i = 4+5*4+5*4+5;
(zuerst Multiplikation, dann Addition)
Sie müssen die Eingabe so geben, als CUBE((4+5))
ob Sie die Zahlen hinzufügen und dann an senden möchten CUBE
. Denn th CUBE(4+5)
wird grundsätzlich erweitert, 4+5*4+5*4+5
da es das Ganze 4+5
an die Stelle von setzt x
. Also, 4+5*4+5*4+5
= 4+20+20+5
wenn die Multiplikation zuerst kommt und dann addiert wird, ergibt sich 49
.
Definieren Sie das Makro so, wie #define CUBE(x) ((x)*(x)*(x))
es tatsächlich ist. Führen Sie zuerst die (4+5)
Operation für jede aus (x)
und führen Sie dann die *
Operation aus.
Eine andere Möglichkeit ist, einfach CUBE((4+5))
beim Aufrufen des Makros zu verwenden. Grundsätzlich werden zuerst die beiden Zahlen und (4+5)
= hinzugefügt 9
und dann CUBE(9)
wie folgt ausgeführt :
#include<stdio.h>
#define CUBE(x) (x * x * x)
int main( )
{
printf("%d", CUBE((4+5)));
return 0;
}
Lesen Moderne C , dann wird der n1570 Entwurf C - Standard, und die Dokumentation von GCC und GDB und der CPP . Siehe auch diese C-Referenzwebsite .
Lassen Sie sich von bestehenden Open Source-Projekten inspirieren, z. B. von Github oder GNU-Software .
Rufen Sie einen aktuellen GCC- Compiler als auf . Verwenden Sie auch die Optionen, um das vorverarbeitete Formular abzurufen.gcc -Wall -Wextra -g
-C -E
Sie könnten auch an der Statement-Expr- Erweiterung von GCC interessiert sein .
Ihr CUBE(4+5)
ist makroerweitert und 4+5*4+5*4+5
wird 4+(5*4)+(5*4)+5
gemäß der Priorität der C-Operatoren berechnet .
Erwägen Sie, eine static inline
Funktion wie zu codieren
static inline int cube(int x) { return x*x*x; }
oder wenn Sie zumindest ein Makro benötigen
#define CUBE(X) ((X)*(X)*(X))
was nicht gut funktioniert CUBE(i++)
(während Sie mit der inline
Funktion cube(i++)
tun , was Sie wollen: i
einmal erhöhen !).
Übrigens könnten Sie GPP oder GNU m4 (oder Ihren eigenen Generator oder GNU Bison ) verwenden, um C-Code zu generieren. Als Faustregel gilt: Denken Sie mit ASTs : Wenn Sie C-Code generieren, geben Sie viele nutzlose Klammern aus, z. B. in Chicken Scheme , SWIG , CAIA oder my manydl.c
Sie können auch den statischen Analysator Clang für Ihren Code (und möglicherweise Frama-C ) verwenden.
Möglicherweise möchten Sie einige Codierungsrichtlinien wie MISRA C oder GNU lesen .