visual c++: __LINE__ geht nicht als ausdruck für 'case' durch



  • C++98 16.8 schrieb:

    The following macro names shall be defined by the implementation:
    _ _LINE_ _ The line number of the current source line (a decimal constant).

    Ist also ein VC bug. Welche VC version?



  • Ben04 schrieb:

    Ist also ein VC bug. Welche VC version?

    seit 7.1 afair.



  • Ben04 schrieb:

    Ist also ein VC bug. Welche VC version?

    die version ist:

    startbanner schrieb:

    Microsoft (R) 32-Bit C/C++-Optimierungscompiler Version 13.00.9466 für 80x86

    ich hab's auch mit dem vc6 probiert. geht ebenfalls nicht.
    gebraucht wird dieses etwas unübliche switch-case übrigens dafür: http://www.sics.se/~adam/pt/
    jammerschade das es nicht geht 😡 , ich hatte bisher eine sehr gute meinung von den m$-compilern 😞

    edit: zum glück gibt's einen workaround: http://support.microsoft.com/default.aspx?scid=kb;en-us;199057



  • Ben04 schrieb:

    C++98 16.8 schrieb:

    The following macro names shall be defined by the implementation:
    _ _LINE_ _ The line number of the current source line (a decimal constant).

    Ist also ein VC bug.

    Nope, ist es nicht. Dir ist schon der Unterschied zwischen constant und constant-expression klar, oder?



  • groovemaster schrieb:

    Nope, ist es nicht. Dir ist schon der Unterschied zwischen constant und constant-expression klar, oder?

    Erklär.



  • ➡ ISO/IEC 14882:2003(E) 😉

    Der Punkt ist einfach der, dass case einen konstanten Ausdruck erwartet. __LINE__ wird aber "lediglich" als Konstante spezifiziert, was alles mögliche, nicht veränderbare sein kann, und nicht zwangsläufig auch bei Erfordernis eines konstanten Ausdrucks gültig sein muss. Insofern muss ein Compiler __LINE__ auch nicht als case Ausdruck akzeptieren. Oder kannst du mir verraten, welche der unterer 5.19 aufgeführten Möglichkeiten für einen konstanten Ausdruck auf den Wert hinter __LINE__ zutreffen?

    Bitte kreuzen sie an:

    [ ] literal
    [ ] enumerator
    [ ] const variable or static data member of integral or enumeration type initialized with constant expression
    [ ] non-type template parameter of integral or enumeration type
    [ ] sizeof expressio
    

    Ich kann da jedenfalls nichts eindeutig zuordnen. Du etwa?

    Vielleicht ist das ja auch nur eine Ungenauigkeit im Standard. Womöglich sollte dort decimal literal oder decimal integral constant-expression stehen. Who knows. Nach aktuellem Stand muss das jedenfalls nicht als Compiler Bug gewertet werden. Höchstens als Nachlässigkeit. 🙂
    Wobei sich für mich die Frage stellt, wieso man __LINE__ überhaupt als case Ausdruck benötigt.



  • Ich vermute, der Abschnitt ist mehr oder weniger wörtlich aus dem C-Standard abgeschrieben. Dort wird "constant" für das verwendet, was im C++-Standard "literal" heißt.

    c99 draft:

    __LINE__ The presumed line number (within the current source
                    file)   of  the  current  source  line  (a  decimal
                    constant).
    

    Ah ja hier, Fußnote aus 2.13 im C++ Draft:

    [Footnote: The term ``literal'' generally designates, in this International Standard, those tokens that are called ``constants'' in ISO C. --- end foonote]

    Fazit: Nachlässigkeit vermutlich.



  • groovemaster schrieb:

    Ben04 schrieb:

    C++98 16.8 schrieb:

    The following macro names shall be defined by the implementation:
    _ _LINE_ _ The line number of the current source line (a decimal constant).

    Ist also ein VC bug.

    Nope, ist es nicht. Dir ist schon der Unterschied zwischen constant und constant-expression klar, oder?

    Ist mir schon klar aber den Sinn decimal davor zu schreiben ergibt sich mir dann nicht.



  • groovemaster schrieb:

    Bitte kreuzen sie an:

    [ ] literal
    [ ] enumerator
    [ ] const variable or static data member of integral or enumeration type initialized with constant expression
    [ ] non-type template parameter of integral or enumeration type
    [ ] sizeof expressio
    

    Ich kann da jedenfalls nichts eindeutig zuordnen. Du etwa?

    das erste (literal) ist damit gemeint.

    btw: es ist definitiv ein bug. guckst du den microsoft-link weiter oben...



  • Ben04 schrieb:

    Ist mir schon klar aber den Sinn decimal davor zu schreiben ergibt sich mir dann nicht.

    Gibt ja auch noch oktal oder hexadezimal und Operator ##.

    net schrieb:

    das erste (literal) ist damit gemeint.

    Sehe gerade, dass du eine C Datei hast (bin von C++ ausgegangen). Dann ist es tatsächlich als Ganzzahlliteral zu werten, da diese dort explizit als constants spezifiziert sind. In C++ sieht das etwas anders aus.

    net schrieb:

    btw: es ist definitiv ein bug. guckst du den microsoft-link weiter oben...

    Dort geht es aber nicht um das konkrete Problem. Lediglich darum, dass durch den Präprozessor __LINE__ falsch evaluiert wird. Damit ist nicht gesagt, dass im Falle von switch/case ebenfalls ein Bug vorliegt. Als Bug kann nur das unterschiedliche Verhalten bei /ZI und /Zi gewertet werden.
    Einigen wir uns also darauf, dass es in C ein Bug ist, in C++ aufgrund der Nachlässigkeit im Standard jedoch keiner (allerdings einer sein sollte). 🙂



  • groovemaster schrieb:

    Ben04 schrieb:

    Ist mir schon klar aber den Sinn decimal davor zu schreiben ergibt sich mir dann nicht.

    Gibt ja auch noch oktal oder hexadezimal und Operator ##.

    Gehen wir davon aus, dass es eine const Variable ist und keine zur Übersetzungszeit bekannte Konstante also wie in folgendem Beispiel die Variable b:

    int a=0;
    const int b = a;
    

    Hier zu fordern, dass b eine decimal Representation hat ist doch Schwachsinn. b ist aber eine Konstante also könnte man __LINE__ auf diese Weise implementiren wie es der VC auch scheinbar macht und aus __LINE__ eine (__LINE__Var+x) macht.

    Sowie ich den Link verstanden hab diehnt das dazu, dass assert und co auch noch die richtige Zeilennumber anzeigt wenn irgendwo während des Debuggen eine Zeile hinzugefügt wird ohne neuübersetzen zu müssen.

    Wenn __LINE__ aber einen zur Übersetzungszeit bekannter Ausdruck wäre dann würde decimal durschaus Sinn machen, um 0x1 und (2-1) zu verbieten.



  • Und worauf willst du hinaus?
    Hinter __LINE__ verbirgt sich nicht einfach nur ein Wert eines Typs, so wie das bei Variablen oder Literalen der Fall ist. Die Repräsentation ist ebenfalls zu beachten, da Makros nunmal nichts anderes als Texte darstellen. Und da macht decimal durchaus Sinn. So wird garantiert, dass zB aus x##__LINE__ nicht irgendwas wie x0x10 wird, sondern x16.



  • groovemaster schrieb:

    Und worauf willst du hinaus?
    Hinter __LINE__ verbirgt sich nicht einfach nur ein Wert eines Typs, so wie das bei Variablen oder Literalen der Fall ist. Die Repräsentation ist ebenfalls zu beachten, da Makros nunmal nichts anderes als Texte darstellen. Und da macht decimal durchaus Sinn. So wird garantiert, dass zB aus x##__LINE__ nicht irgendwas wie x0x10 wird, sondern x16.

    Wenn __LINE__ durch 123 oder ähnlich in jedem Fall ersetz werden würde dann müsste auch "case __LINE__:" funktionieren da nachdem der Präprocessor drüber gelaufen ist es keine Möglichkeit für den Compiler mehr gibt 123 von 123 zu unterscheiden.

    Da es deiner Meinung nach aber legal ist "case __LINE__:" abzulehenen ist es auch legal __LINE__ zu etwas anderem als 123 expandiren zu lassen (da man es sonst gar nicht ablehnen kann). Da es sich um eine Laufzeitkonstante handeln muss (da man es sonst ja nicht abgelehnt werden würde) bleibt eigentlich als einzige Möglichkeit eine compilerinterne Variable.

    Bei einer compilerinterne Variable von decimal ist aber Schwachsinn. Das bedeute also, dass es nicht erlaubt ist eine compilerinterne Variable zu verwenden. Die einzige Alternative ist ein Integerliteral oder die Combination mehrer Literale (1+1) und in beiden Fälle würde "case __LINE__:" kompiliert werden.

    Hast du jetzt verstanden worauf ich hinaus will?

    auch nicht sagen was bei x##__LINE__ rauskommt.

    Die einzige Situation in der der Kompiler



  • Ben04 schrieb:

    Wenn __LINE__ durch 123 oder ähnlich in jedem Fall ersetz werden würde

    Und wer garantiert dir das?

    Ben04 schrieb:

    Da es deiner Meinung nach aber legal ist "case __LINE__:" abzulehenen ist es auch legal __LINE__ zu etwas anderem als 123 expandiren zu lassen

    Korrekt. Es geht dabei aber nicht um den Wert ansich, sondern einzig und allein um die Repräsetation dessen.

    Ben04 schrieb:

    Bei einer compilerinterne Variable von decimal ist aber Schwachsinn.

    Du hast immer noch nicht kapiert, dass Makros nicht zu Werten, sondern zu Texten evaluieren.

    Vielleicht hast du mich ja auch falsch verstanden. Ich sage nicht, dass es falsch ist, wenn case __LINE__ akzeptiert. Ich sage lediglich, dass es aufgrund der Unzulänglichkeiten im Standard kein Bug ist, wenn es nicht so ist. Wie ich weiter oben schon sagte, das einzige was beim MSC als Bug zu werten ist, ist das unterschiedliche Verhalten bei unterschiedlichen Compilereinstellungen.



  • groovemaster schrieb:

    Korrekt. Es geht dabei aber nicht um den Wert ansich, sondern einzig und allein um die Repräsetation dessen.

    Ok kannst du mir irgendeine mögliche Expansion von __LINE__ nennen die
    a) kein Ganzzahlenliteral (oder zur Übersetzungszeit bekannter Ausdruck) ist.
    b) in einer decimalen Representation ist.
    Ich kenne jedenfals nichts das sowohl a) wie auch b) genügt und per Ausschlussverfahren heißt das, dass __LINE__ zu einem decimalen Ganzzahlenliteral expandiren muss.



  • Ben04 schrieb:

    a) kein Ganzzahlenliteral

    Ein Präprozessor könnte bei

    cout << __LINE__ << endl;
    

    zB sowas machen

    cout << (__Internal_line_42 + xx) << endl;
    

    , was vom Compiler dann entsprechend verarbeitet wird. Normalerweise sollten Präprozessor und Compiler voneinander unabhängig arbeitende Einheiten sein, der MSC scheint das aber nicht so eng zu sehen. Ich wüsste auch nichts, was seitens des Standards dagegen sprechen sollte.

    Ben04 schrieb:

    b) in einer decimalen Representation ist.

    s.o.

    Ich denke, es wurde von meiner Seite alles gesagt. Und dabei wollen wir es belassen. Finde dich damit ab, dass der MSC es nicht akzeptiert. Ob du es nun Bug nennst oder nicht, spielt letztendlich keine Rolle. Seitens des Standards ist dies aufgrund gewisser Unzulänglichkeiten nicht zweifelsfrei nachweisbar, imo.



  • groovemaster schrieb:

    cout << __LINE__ << endl;
    

    zB sowas machen

    cout << (__Internal_line_42 + xx) << endl;
    

    , was vom Compiler dann entsprechend verarbeitet wird...

    mag ja sein, aber diese verarbeitung muss so aussehen, dass er (__Internal_line_42 + xx) als zahl nimmt, und zwar so, als hätte jemand eine dezimalzahl hingeschrieben. alles andere geht nicht...



  • groovemaster schrieb:

    cout << (__Internal_line_42 + xx) << endl;
    

    IMO wird b) daruch nicht erfüllt.

    groovemaster schrieb:

    s.o.

    "siehe oben" oder für was soll das stehen?

    Dein x##__LINE__ ist jedenfals undefiniert fals dein Vorschlag b) erfüllen würde.


Anmelden zum Antworten