2015-06-30 4 views
15

erhalten Gibt es eine Möglichkeit, den C-Compiler (XC16 in meinem Fall, der auf gcc basiert) die Ergebnisse von Kompilierungszeitausdrücken auszugeben?den Wert der Ausdrücke zur Kompilierungszeit in C

Wir haben viele #defines wie

#define FOO 37.6 
#define FOO_BASE 0.035 
#define FOO_FIXEDPOINT (int16_t)(FOO/FOO_BASE) 

und ich würde die tatsächlichen Zahlen wissen, dass der Compiler, um diese Ausdrücke reduziert.

Beachten Sie, dass dies NICHT ist die gleiche Sache wie zu wissen, was der Präprozessor ausgibt; Der Präprozessor berechnet keine Mathematik, er ersetzt nur Dinge. Wenn ich an der Präprozessorausgabe aussehen, erhalte ich (effektiv)

#define FOO_FIXEDPOINT (int16_t)(37.6/0.035) 

und es ist die Compiler, nicht der Prä-Prozessor, der einen Wert herausfindet.


Ein weiterer wichtiger Punkt hier: Ich habe nicht die Freiheit, eine spezielle C-Datei zu erstellen, die Dinge wie

#include "foo.h" 

const int16_t foo_fixedpoint = FOO_FIXEDPOINT; 

so tut, dass ich einen Platz für den Compiler bin Bereitstellung seiner Arbeit zu tun und stelle die Ergebnisse als Konstante dar.


nur als komplettes umluftunabhängigem Beispiel, wenn ich dies in der foo.c und laufen xc16-gcc.exe -E foo.c:

#include <stdint.h> 

#define FOO 37.6 
#define FOO_BASE 0.035 
#define FOO_FIXEDPOINT (int16_t)(FOO/FOO_BASE) 

int main() 
{ 
    int x = FOO_FIXEDPOINT; 
} 

ich diese Ausgabe erhalten:

[... typedefs elided ...] 
int main() 
{ 
    int x = (int16_t)(37.6/0.035); 
} 
+4

Lasen Sie das Handbuch? * gcc * hat einen '-E' Schalter, um nur den Präprozessor zu starten. –

+6

bitte rtfm mich nicht. Um das zu tun, muss ich wissen, wonach ich suchen muss. –

+0

@GrzegorzSzpetkowski - nein, keine gdb (die ich kenne) für den DSPIC. Außerdem sind Dutzende dieser Definitionen im Code verstreut, sodass ich sie alle automatisch löschen möchte. –

Antwort

14

Überprüfen Sie die Flags -fdump-tree-* in der debugging options Seite, um die Ausgabe der Zwischensprache zu sehen (ein bisschen Low-Level, aber durchaus lesbar).

Sie können -fdump-tree-all verwenden, um die Datei in verschiedenen Phasen zu sehen, aber wahrscheinlich ist alles, was Sie brauchen, die -fdump-tree-original.Schauen Sie unten unten in der generierten *.original Datei für Ihre Hauptfunktion aussehen:

... 
;; Function main (null) 
;; enabled by -tree-original 

{ 
    int x = 1074; 

    int x = 1074; 
} 
+1

Hmm. Noch eine Frage. Warum funktioniert das so? wenn es der "ursprüngliche" AST ist, wie kommt es, dass die konstante Faltung vor diesem Punkt stattfindet? –

+1

@JasonS Ich weiß nicht, wie, aber grundlegende Ausdrücke (z. B. 3 + 4) scheint viel früher vor Baumoptimierungen Phase ausgewertet werden. –

1

EDIT Das funktioniert nicht :-(

Auch mit dem Trick für co Wenn der Ganzzahlwert in eine Zeichenfolge umgewandelt wird, wird der zusammengesetzte Wert nicht vom Präprozessor ausgewertet.

#define STR_HELPER(x) #x 
#define STR(x) STR_HELPER(x) 

#define A 1 
#define B 2 
#define C A+B 

#pragma message("A=" STR(A)) 
#pragma message("B=" STR(B)) 
#pragma message("C=" STR(C)) 

Compiler-Ausgang (VS2008):

1>A=1 
1>B=2 
1>C=1+2 

So Präprozessor hier nicht helfen.

Original-ANTWORT Als letzten Ausweg, wenn es keine Möglichkeit gibt, die Werte aus den Zwischen Dateien bekommen, mittels gcc-Optionen usw.

ich die Quelle-Dateien für # grep würde define, leite die Ausgabe in eine neue .c-Datei um und ersetze #define durch #pragma message. Der Aufruf von gcc für diese Datei listet alle Definitionen auf. Natürlich vorausgesetzt Ihr Compiler unterstützt #pragma message.

+0

hmm. Dies ermöglicht dem Compiler, mathematische Berechnungen durchzuführen und die Ergebnisse als Nachricht auszugeben ?! –

+0

Leider funktioniert Pragma-Nachricht nur auf Strings, und das OP fragt nach berechneten numerischen Werten. Er müsste eigentlich (für Gleitkommakonstanten) printf kompilieren ("% f \ n", MACRO); – Gene

+0

ah ... ja, und die Verwendung von printfs ist eine hässliche Sache, weil dies ein Cross-Compiler für ein eingebettetes System ist. –

2

Wie in den Kommentaren diskutiert, vor allem, wenn die numerischen Makros werden mit Makros gemischt mit nicht-numerischen Typen, es ist einfach ein Programm zu produzieren, Gibt ihre Werte aus.

Obwohl Ihre Umgebung ein Cross-Compiler ist, ist dies eine nützliche Übung, da alle gccs konstante Ausdrücke intern mit demselben Code verarbeiten. Dies macht Mathematik in erweiterter Genauigkeit, so dass kompilierte Konstanten innerhalb eines ULP des exakten Werts liegen.

Also sollte jeder gcc eine ziemlich genaue Vorstellung davon geben, was in Ihrem Code passiert.

In Perl:

print "#include<stdio.h>\n"; 
print "#include \"$ARGV[0]\"\n"; 
print "#define S(X) #X\n"; 
print "int main(void) {\n"; 
open F, $ARGV[0] or die $!; 
while (<F>) { 
    print " printf(\"%s=%.13g\\n\", S($1), (double)$1);\n" if /#define\s+(\w+)\s+\S/; 
} 
print " return 0;\n}\n"; 

Jetzt versuchen es auf math.h durch Neige.

perl /usr/include/math.h > math_h_syms.c 

Dies erzeugt:

#include<stdio.h> 
#include "/usr/include/math.h" 
#define S(X) #X 
int main(void) { 
    printf("%s=%.13g\n", S(INFINITY), (double)INFINITY); 
    printf("%s=%.13g\n", S(FP_NAN), (double)FP_NAN); 
    printf("%s=%.13g\n", S(FP_INFINITE), (double)FP_INFINITE); 
    printf("%s=%.13g\n", S(FP_ZERO), (double)FP_ZERO); 
    printf("%s=%.13g\n", S(FP_NORMAL), (double)FP_NORMAL); 
    printf("%s=%.13g\n", S(FP_SUBNORMAL), (double)FP_SUBNORMAL); 
    printf("%s=%.13g\n", S(FP_SUPERNORMAL), (double)FP_SUPERNORMAL); 
    printf("%s=%.13g\n", S(FP_ILOGB0), (double)FP_ILOGB0); 
    printf("%s=%.13g\n", S(FP_ILOGBNAN), (double)FP_ILOGBNAN); 
    printf("%s=%.13g\n", S(MATH_ERRNO), (double)MATH_ERRNO); 
    printf("%s=%.13g\n", S(MATH_ERREXCEPT), (double)MATH_ERREXCEPT); 
    printf("%s=%.13g\n", S(math_errhandling), (double)math_errhandling); 
    printf("%s=%.13g\n", S(M_E), (double)M_E); 
    printf("%s=%.13g\n", S(M_LOG2E), (double)M_LOG2E); 
    printf("%s=%.13g\n", S(M_LOG10E), (double)M_LOG10E); 
    printf("%s=%.13g\n", S(M_LN2), (double)M_LN2); 
    printf("%s=%.13g\n", S(M_LN10), (double)M_LN10); 
    printf("%s=%.13g\n", S(M_PI), (double)M_PI); 
    printf("%s=%.13g\n", S(M_PI_2), (double)M_PI_2); 
    printf("%s=%.13g\n", S(M_PI_4), (double)M_PI_4); 
    printf("%s=%.13g\n", S(M_1_PI), (double)M_1_PI); 
    printf("%s=%.13g\n", S(M_2_PI), (double)M_2_PI); 
    printf("%s=%.13g\n", S(M_2_SQRTPI), (double)M_2_SQRTPI); 
    printf("%s=%.13g\n", S(M_SQRT2), (double)M_SQRT2); 
    printf("%s=%.13g\n", S(M_SQRT1_2), (double)M_SQRT1_2); 
    printf("%s=%.13g\n", S(MAXFLOAT), (double)MAXFLOAT); 
    printf("%s=%.13g\n", S(FP_SNAN), (double)FP_SNAN); 
    printf("%s=%.13g\n", S(FP_QNAN), (double)FP_QNAN); 
    printf("%s=%.13g\n", S(HUGE), (double)HUGE); 
    printf("%s=%.13g\n", S(X_TLOSS), (double)X_TLOSS); 
    printf("%s=%.13g\n", S(DOMAIN), (double)DOMAIN); 
    printf("%s=%.13g\n", S(SING), (double)SING); 
    printf("%s=%.13g\n", S(OVERFLOW), (double)OVERFLOW); 
    printf("%s=%.13g\n", S(UNDERFLOW), (double)UNDERFLOW); 
    printf("%s=%.13g\n", S(TLOSS), (double)TLOSS); 
    printf("%s=%.13g\n", S(PLOSS), (double)PLOSS); 
    return 0; 
} 

Kompilieren und Ausführen:

INFINITY=inf 
FP_NAN=1 
FP_INFINITE=2 
FP_ZERO=3 
FP_NORMAL=4 
FP_SUBNORMAL=5 
FP_SUPERNORMAL=6 
FP_ILOGB0=-2147483648 
FP_ILOGBNAN=-2147483648 
MATH_ERRNO=1 
MATH_ERREXCEPT=2 
math_errhandling=2 
M_E=2.718281828459 
M_LOG2E=1.442695040889 
M_LOG10E=0.4342944819033 
M_LN2=0.6931471805599 
M_LN10=2.302585092994 
M_PI=3.14159265359 
M_PI_2=1.570796326795 
M_PI_4=0.7853981633974 
M_1_PI=0.3183098861838 
M_2_PI=0.6366197723676 
M_2_SQRTPI=1.128379167096 
M_SQRT2=1.414213562373 
M_SQRT1_2=0.7071067811865 
MAXFLOAT=3.402823466385e+38 
FP_SNAN=1 
FP_QNAN=1 
HUGE=3.402823466385e+38 
X_TLOSS=1.414847550406e+16 
DOMAIN=1 
SING=2 
OVERFLOW=3 
UNDERFLOW=4 
TLOSS=5 
PLOSS=6 
+0

seltsame Zahlen für die nan/unendlich/etc .... –

+0

@JasonS: na ja. 'math.h' definiert diese als" Rückgabewerte für fpclassify "(obwohl meine lokalen mingw-Werte unterschiedlich sind). – usr2564301

Verwandte Themen