2016-04-08 10 views
3

Frage

Ich bin gespannt, ob es irgendwelche Garantien über konstante Faltunggarantierte Mindest Constant Folding in C

in C. getan, wo ich

haben gesucht

This link auf einer Website, deren Seriosität ist unbekannt für mich macht einen offenen Kommentar:

Alle C-Compiler können Integer-Konstantenausdrücke falten, die nach Makroerweiterung vorhanden sind (ANSI C-Anforderung).

Aber ich sehe nichts in z.B. Die C-Programmiersprache, zweite Ausgabe (von der ich annahm, dass sie gründlich aktualisiert wurde, um alle Details von ANSI C zu berücksichtigen). Aber nachdem ich den Index auf Verweise auf relevante Wörter überprüft habe, habe ich nichts gefunden, was das verspricht. Insbesondere die Seiten 38 und 209 kommen nahe, weil sie sagen, jeder Ausdruck, der zur Kompilierungszeit könnte ausgewertet werden könnte, wo eine Konstante verwendet werden könnte (vielleicht mit einigen Einschränkungen, wenn wir pedantisch genug sind), und es sagt solche Ausdrücke "kann" zur Kompilierzeit ausgewertet werden, nicht "wird"/(irgendein Synonym).

Ich suchte this C89 final draft. Das Wort "falten" und "gefalten" ergab keine Werte, und die Suche "konstanter Ausdruck" erzeugte 63 Treffer, von denen ich etwa die Hälfte überprüfte. Der primäre Teil von Interesse scheint im Grunde das gleiche wie das Buch zu sein (es verwendet das Wort "kann" statt "kann", aber das sind auch in diesem Zusammenhang).

Beide scheinen logisch stark zu meinen, dass jeder ANSI-C-Compiler grundlegende Funktionen zum konstanten Falten haben muss, aber gleichzeitig scheint es kein hartes Verbot zu geben, konstante Ausdrücke in Code zu kompilieren die den Ausdruck zur Laufzeit berechnet (eine solche Implementierung profitiert immer noch von konstanten Ausdrücken, da der Compiler Code generieren kann, der ihn einmal berechnet und dann annimmt, dass sich der Wert nicht ändert und eine solche Implementierung durch Einschränkungen in einer zugrunde liegenden Architektur erzwungen werden kann) zB müssen mehrere RISC-Architekturen entweder zwei Anweisungen verwenden, um bestimmte mögliche Werte zu initialisieren, oder sie von einem Speicherort laden.

Ich suchte auch kurz this C99 final draft, aber "Faltung" ergab ein Ergebnis von keinem Wert, während "gefaltet" und "konstant" hatte mehr als hundert Übereinstimmungen, die ich derzeit nicht die Zeit zum Durchkriechen zuweisen konnte.

Motivation

Ich schrieb dieses Makros für mehr semantische/Absicht Klarheit in einigen Code-Bit-Fummeln:

#define UCHAR_LOW_N_BITS_m(n) (unsigned char)(UCHAR_MAX >> (CHAR_BIT - (n))) 
#define UCHAR_NTH_BIT_m(n) (unsigned char)(1 << (n)) 

..wo n ist immer ein Ganzzahlliteral. Ich möchte besänftigt sein, um eine beruhigende Stimme zu hören: "Es ist in Ordnung, jeder C-Compiler, der im Entferntesten eine Rolle spielt, wird diese Konstanten für dich falten". (P.S. Ich fragte eine separate Frage darüber, ob UCHAR_NTH_BIT_m sollte als ob bits start from the 0th or 1st bit, hoffentlich an der richtigen Stelle handeln.)

Und ja, die untere könnte in separate Makros, z.#define UCHAR_1ST_BIT_m (unsigned char)1 durch #define UCHAR_3RD_BIT_m (unsigned char)4 oder wie viele ich im Code auch brauche - und während ich unentschlossen bin, welche von denen besser ist, ist es wahrscheinlich ein strittiger Punkt, denn wenn ich ein guter pedantisch-sprachlicher Anwalt sein will, Typ C Programmierer, ich kann nicht genau das Top vermeiden (muss sicherstellen, dass der Code das Richtige auf diesen DSP/embedded und ancient-Mainframe C-Implementierungen tut).

+1

Es liegt beim Compiler-Entwickler. "Can" ist amerikanisch für "may" und bedeutet, dass Sie dürfen, aber Sie müssen es nicht tun. Und ja, jeder gute Compiler wird es tun. –

+0

Ich glaube nicht, dass die Verwendung von "Can" auf amerikanisches Englisch beschränkt ist. – dreamlax

+0

@ KlasLindbäck: Ich schätze die Klarstellung, aber ich war mir bewusst: Deshalb sagte ich "scheint im Grunde gleich zu sein" - weil ich verstand, dass, obwohl es einen Wortunterschied gab, es im Wesentlichen dasselbe bedeutete. Ich werde es bearbeiten, um die Möglichkeit weiterer Missverständnisse zu verringern. – mtraceur

Antwort

5

In der C-Norm wird der Begriff für Compile-Zeit ist Übersetzungszeit und Ereignisse, die zum Zeitpunkt der Kompilierung passieren können als während der Übersetzung beschrieben. Sie können den Standard nach diesen Begriffen durchsuchen.

Am nächsten an diesem Thema in diesem Standard ist die Definition von konstanten Ausdruck in Abschnitt 6.6 (C11). Die Übersicht lautet:

Ein konstanter Ausdruck kann während der Übersetzung und nicht der Laufzeit ausgewertet werden und kann daher an jeder Stelle verwendet werden, an der eine Konstante stehen kann.

Beachten Sie, dass "can be" nicht bedeutet "muss sein". Wir würden erwarten, dass ein Compiler mit guter Qualität konstante Ausdrücke zur Kompilierungszeit auswertet, obwohl dies keine absolute Anforderung ist.

Abschnitt 6.6 ist zu groß, die ganze Sache hier einzufügen, sondern durch die C Standard Beratung (oder einen Entwurf wie N1570) können Sie über die lesen Ausdrücke definiert werden als konstante Ausdrücke und es wäre vernünftig anzunehmen, dass Ihr Compiler sie zur Kompilierzeit auswertet.

Wenn n >= 0 && n < CHAR_BIT * sizeof(int) - 1 und n eine ganze Zahl konstanter Ausdruck, dann (unsigned char)(1 << (n)) ist eine Integer-Konstante Ausdruck da: seine Operanden ganzzahlige Konstanten sind, ist es nicht einer der Operatoren ist, die in konstanten Ausdrücken verboten sind (zB ++), und die Umwandlung ist zulässig, da sie vom Integer-Typ in einen anderen Integer-Typ umgewandelt wird.

Wenn n außerhalb dieses Bereichs liegt, ist der Ausdruck kein konstanter Ausdruck und verursacht nicht definiertes Verhalten.

Ihr anderer Ausdruck ist ähnlich; es ist ein ICE, solange CHAR_BIT - n in denselben gültigen Bereich fällt.

4

Im Allgemeinen gibt der C-Standard nicht an, wie etwas kompiliert wird. Sie werden niemals eine Garantie erhalten, dass eine Möglichkeit, etwas zu implementieren, schneller ist als eine andere. Es gibt keine Garantie dafür, dass eine konstante Faltung stattfinden muss, aber da der Compiler konstante Ausdrücke zur Kompilierungszeit auswerten muss (um #if Direktiven und Array-Deklaratoren zu verarbeiten), ist es sehr wahrscheinlich, dass der Compiler eine konstante Faltung ausführt. Es macht schließlich keinen Sinn, konstant falten zu können, aber dann nicht.

+0

Das ist mehr oder weniger was ich dachte. Ich habe dies getan, und ich werde es in ein oder zwei Tagen akzeptieren, wenn keine bessere Antwort erscheint. – mtraceur

+0

Der Inhalt von '# if'-Direktiven wird vom Präprozessor ausgewertet, nicht vom Compiler, aber konstante Ausdrücke sind in Array-Deklarationen erlaubt, die vom Compiler gehandhabt werden. – supercat

+0

@supercat Der Standard sagt nicht, wie der Compiler implementiert ist, er spezifiziert lediglich eine Reihe von Übersetzungsphasen, von denen die ersten im Preprozessor allgemein implementiert sind. – fuz