2016-05-15 8 views
4

Ich machte das Code-Snippet einfacherWie funktioniert C Präprozessor tatsächlich?

// Example 1 

#define sum2(a, b) (a + b) 
#define sum3(a, b, c) (sum2(a, sum2(b, c))) 

sum3(1, 2, 3) // will be expanded to ((1 + (2 + 3))) 


// Example 2 

#define score student_exam_score 
#define print_score(student_exam_score) printf("%d\n", score) 
#undef score 

print_score(80); // will be expanded to printf("%d\n", score); 
       // but not printf("%d\n", 80); that I expect 

Die erste ist intuitiv, zu erklären, und dass Arten von Codes existiert in mehreren Orten wie die maximale oder minimale Anzahl zu finden. Allerdings möchte ich diese Technik verwenden, um meinen Code sauber und leicht lesbar zu machen, also ersetze ich die Wörter in einem Makro durch einen kürzeren und aussagekräftigeren Namen.

AFAIK, C-Präprozessor wird nur einmal pro Kompilierungseinheit ausgeführt und führt nur Stringersatz durch, aber warum print_score kann nicht auf printf("%d\n", 80); erweitert werden?

Dies ist die Ersetzungsprozedur ich denke:

#define score student_exam_score 
#define print_score(student_exam_score) printf("%d\n", score) 
#undef score 

print_score(80); 

// --> 

#define score student_exam_score // runs this first 
#define print_score(student_exam_score) printf("%d\n", student_exam_score) // changed 
#undef score 

print_score(80); 

// --> 

#define score student_exam_score 
#define print_score(student_exam_score) printf("%d\n", student_exam_score) // then this 
#undef score 

printf("%d\n", 80); // changed 
+0

print_score (80); => printf ("% d \ n", score) => printf ("% d \ n", student_exam_score), das ist das Problem. – BlackMamba

+0

@BlackMamba Wird 'print_score (student_exam_score) printf ("% d \ n ", score)' nicht durch 'print_score (student_exam_score) printf ("% d \ n ", student_exam_score)' zuerst ersetzt? –

+1

"* C-Präprozessor läuft nur einmal pro Kompilierungseinheit *" und "* warum' print_score' kann nicht auf 'printf ("% d \ n ", 80) erweitert werden;'? * "Letzteres liegt genau an ersterem. – alk

Antwort

3

Es ist eine Frage der Reihenfolge. Zuerst werden die Makros definiert und score ist undefiniert, bevor es überhaupt verwendet wird. Dann, wenn print_score erweitert wird, ersetzt es zuerst alle Instanzen von student_exam_score, von denen es keine gibt. Anschließend wird das Ergebnis erneut gescannt und nach weiteren Makros zum Erweitern gesucht. Es sind jedoch keine vorhanden, da score nicht definiert wurde und nicht mehr verfügbar ist.

Auch wenn Sie #undef score unten unter dem Verweis auf print_score bewegt, wäre es immer noch nicht funktionieren, da nur Parameter Substitution einmal passiert (score erweitert werden würde, aber student_exam_score würde nicht).

Beachten Sie, dass score nicht in den Körper von print_score zu der Zeit substituiert ist, ist es definiert. Die Substitution tritt nur auf, wenn das Makro instanziiert wird, weshalb #undef score in dem score Makro keinerlei Wirkung hat.

Diese Beispiele machen es klarer. Zuerst sollten Sie Folgendes beachten:

#define foo bar 
#define baz(bar) (foo) 
baz(123) 

Dieser wird wie folgt ergänzt:

baz(123) 
-> (foo) 
-> (bar) 

Expansion stoppt hier. Die Parameterersetzung wurde durchgeführt, bevor foo erweitert wurde und nicht erneut auftritt.

Betrachten wir nun die folgenden:

#define foo bar 
#define baz(bar) (foo) 
#undef foo 
baz(123) 

Dieser wird wie folgt ergänzt:

baz(123) 
-> (foo) 

Expansion stoppt hier, weil foo nicht mehr definiert. Seine frühere Definition hatte keinen Einfluss auf die Definition von baz, da Makro-Substitution nicht stattfindet, wenn Makros definiert sind. Es passiert nur, wenn sie erweitert werden.

+0

Warum ist "Score" undefined?Ich bin mir nicht sicher, ob die Vorverarbeitung über undefiniert ist. –

+0

Es ist ein Sequenzierungsproblem. '#undef score' undefiniert' score' bevor es jemals benutzt wurde. Siehe den letzten Abschnitt meiner Antwort, den ich gerade hinzugefügt habe. –

+0

'# undef' existiert nur, um den folgenden Code nicht zu beeinflussen. –

Verwandte Themen