Interner Typ einer Enum-Konstante



  • Ahoy, Leute.
    Ich habe folgenden Code:

    /*****************************************************************************
    **Zeittyp einer Datei. Auf *nix-Systemen gibt es drei Typen fuer Dateien:
    **letzter Zugriff, letzte Modifikation und Statusänderung.
    *****************************************************************************/
    enum FILES_COT
    {
        FILES_COT_A,
        FILES_COT_M,
        FILES_COT_C
    };
    

    Hierbei handelt es sich eigentlich nur um einen bestimmten Wertebereich, den eine Reihe von Funktionen als Parameter übernimmt. Um undefiniertes Verhalten durch einen Fehler des aufrufenden Programmierers/durch eine Sicherheitslücke, die es eventuell erlaubt, das Argument zu verändern, zu verhindern, habe ich einen Check für diesen Typen definiert:

    #define FILES_COT_IS_SANE(x) (FILES_COT_A<=(x) && (x)<=FILES_COT_C)
    

    Wenn also ein Wert unter der ersten oder ein Wert über der letzten Konstante angegeben wurde, soll das Makro 0 zurückliefern.

    Soweit sogut. Aber jetzt haut mir der GCC hierfür Warnungen raus:

    Warnung: Vergleich eines vorzeichenlosen Ausdrucks >= 0 ist stets »wahr« [-Wtype-limits]
    Warnung: Vergleich eines vorzeichenlosen Ausdrucks >= 0 ist stets »wahr« [-Wtype-limits]
    

    Der vom Präprozessor generierte Ausdurck sieht so aus:

    if(!(FILES_COT_A<=(wobj->ifrt_ifc) && (wobj->ifrt_ifc)<=FILES_COT_C))
    

    wobj->ifrt_ifc ist vom enum-Typ FILES_COT :

    struct files_remove_on_time_t
    {
        /*...*/
        const enum FILES_COT ifrt_ifc;
        /*...*/
    }
    

    Eventuell habe ich gerade einen kompletten Blackout, aber ich habe noch gelernt, dass der Typ der Konstanten eines Enums int ist. int ist vorzeichenbehaftet. Ich habe keine Compileroption aktiviert, die dies ändern würde:

    gcc ./src/files.c -I include/ <ein paar vorkompilierte Header> -O2 -E
    

    Mein Problem ist folgendes: ich dachte bisher, dass die Konstanten vom Typ int sind, und daher auch vorzeichenbehaftete (sprich, negative) Zahlen aufnehmen können. Dann würde der Check auf 0<=-1 Sinn ergeben. Der Compiler scheint aber in diesem Moment da einfach 0<=0xFFFFFFFF zu sehen. Aber dann scheint der GCC das doch auch nicht so zu sehen ...

    #include <stdio.h>
    
    enum A
    {
        A_A,
        A_B,
        A_C
    };
    
    int main(void)
    {
        enum A my_a=(-1);
        printf("%d\n",my_a);
        return 0;
    }
    

    Kompiliert mit:

    gcc enums.c -o enum -Wextra -Wall -Wimplicit -fstack-protector -Wunused-parameter
    

    Gibt keinen Fehler/Warnung aus.
    Könnte mich jemand erleuchten, wo mein Denkfehler liegt? Ich habe grad irgendwie ein Brett vor dem Kopf.



  • Was hat** wobj->ifrt_ifc **für einen Typ?



  • Scheiße, hatte vergessen, den zu erwähnen. Hatte ich aber schon geprüft, dass der keine automatische Typenkonvertierung macht:

    struct files_remove_on_time_t
    {
        /*...*/
        const enum FILES_COT ifrt_ifc;
        /*...*/
    }
    


  • gcc-Eigenart einer Optimierung, weil dokumentiert aber konform zum Standard.

    Normally, the type is unsigned int if there are no negative values in the enumeration, otherwise int.
    https://gcc.gnu.org/onlinedocs/gcc-4.4.0/gcc/Structures-unions-enumerations-and-bit_002dfields-implementation.html

    Dürfte sich beheben lassen z.B. durch

    enum FILES_COT
    {
        DUMMYENUM = -1,
        FILES_COT_A,
        FILES_COT_M,
        FILES_COT_C
    };
    


  • Ach, wie nett. Das sind ja tolle Optimierungen, die genau dann zuschlagen, wenn man sicherstellen will, dass keine ungültigen Werte angegeben werden. *würg*

    Danke dir. Der vorgeschlagene Workaround funzt auch - unelegant, aber was tut man nicht für diese Marodeure ...


  • Mod

    dachschaden schrieb:

    Ach, wie nett. Das sind ja tolle Optimierungen, die genau dann zuschlagen, wenn man sicherstellen will, dass keine ungültigen Werte angegeben werden. *würg*

    Danke dir. Der vorgeschlagene Workaround funzt auch - unelegant, aber was tut man nicht für diese Marodeure ...

    Inwiefern hindert dich diese Optimierung an der Prüfung auf ungültige Werte und inwiefern ist dieser Workaround hier überhaupt nötig? Wenn dir jemand eine -1 übergibt, schlägt schließlich die Prüfung auf Werte > FILES_COT_C an.



  • dachschaden schrieb:

    Ach, wie nett. Das sind ja tolle Optimierungen, die genau dann zuschlagen, wenn man sicherstellen will, dass keine ungültigen Werte angegeben werden. *würg*

    Danke dir. Der vorgeschlagene Workaround funzt auch - unelegant, aber was tut man nicht für diese Marodeure ...

    Ich würde gcc die Optimierun auch erlauben und stattdessen die Warnung an dieser Stelle abschalten.

    Geht das mit nem pragma?

    Mfg Martin



  • Wenn man für Compiler portabel bleiben möchte, die keine unsigned enums haben.



  • DirkB schrieb:

    Wenn man für Compiler portabel bleiben möchte, die keine unsigned enums haben.

    Deshalb würde ich die Prüfung drinnen lassen und die Warnung ignorieren odrr abschalten.

    Mfg Martin


Anmelden zum Antworten