Compilefehler nur mit einem Compiler



  • Hi,

    ich verwende Funktionen mit variablen Parameterlisten nach folgendem Prinzip:

    static int getIntValue(const int min,const int max,va_list *vl)
    {
       int   listValue;
    
       listValue=va_arg(*vl,int);
       if (listValue<min) listValue=min;
       else if (listValue>max) listValue=max;
       return listValue;
    }
    
    unsigned long init_if_list(int *var,va_list vl)
    {
       char *listTag;
    
       listTag=va_arg(vl,char*);
       if (!strcmp(listTag,INIT_SHOWUI)) initValues.uiFlags=getIntValue(INT_MIN,INT_MAX,&vl);
    

    Das compiliert und funktioniert problemlos mit VisualStudio 201x und GCC 4.7.x oder älter. Mit dem GCC 4.8.x unter Ubuntu/64 erhalte ich folgende Fehlermeldung:

    error: cannot convert '__va_list_tag**' to '__va_list_tag (*)[1]' for argument '3' to 'int getIntValue(int, int, __va_list_tag (*)[1])'
       if (!strcmp(listTag,INIT_SHOWUI))                initValues.uiFlags=getIntValue(INT_MIN,INT_MAX,&vl);
    

    Ändere ich meinen Code jetzt dahingehend ab, das va_list nicht mehr als Pointer übergeben wird:

    static int getIntValue(const int min,const int max,va_list vl)
    {
       int   listValue;
    
       listValue=va_arg(vl,int);
       if (listValue<min) listValue=min;
       else if (listValue>max) listValue=max;
       return listValue;
    }
    
    unsigned long init_if_list(int *var,va_list vl)
    {
       char *listTag;
    
       listTag=va_arg(vl,char*);
       if (!strcmp(listTag,INIT_SHOWUI)) initValues.uiFlags=getIntValue(INT_MIN,INT_MAX,vl);
    

    schmiert mir der Krempel mit VisualStudio und GCC 4.7 Code ab. Was nun? Wieso hat sich der GCC 4.8 da plötzlich kleinlich und wie müsste der Code aussehen, damit er mit allen Compilern funktioniert?

    Danke!



  • Zarc schrieb:

    wie müsste der Code aussehen, damit er mit allen Compilern funktioniert?

    Die Antwort ist immer: standardkonform

    Das was du hier zeigst, ist schlimmstes Rumgefrickel, du probierst irgendwas aus was irgendwie gerade noch compiliert und jammerst anschließend rum.
    Du hast das Prinzip im Umgang mit variablen Parametern nicht verstanden.
    C-Standard und vargs



  • Wutz schrieb:

    Die Antwort ist immer: standardkonform

    Sorry, aber das ist eine vollkommen nutzlose Antwort.

    Wutz schrieb:

    Das was du hier zeigst, ist schlimmstes Rumgefrickel, du probierst irgendwas aus was irgendwie gerade noch compiliert und jammerst anschließend rum.

    ...dann kommt eine Beleidiging...

    Wutz schrieb:

    Du hast das Prinzip im Umgang mit variablen Parametern nicht verstanden.
    C-Standard und vargs

    ...gefolgt von einem Link auf ein völlig übertriebenes Monsterdokument. Wenn du nicht helfen kannst oder willst, was antwortest du dann überhaupt? Versuchst du deine schlechte Laune an jemandem auszulassen?



  • Wutz hat vollkommen Recht, der Link ist genau die Antwort auf Dein Problem und eine Beleidung kann ich auch nicht sehen ... RTFM.



  • Zorc schrieb:

    ...gefolgt von einem Link auf ein völlig übertriebenes Monsterdokument.

    Du hast keine Ahnung wovon du redest.
    Das "übertriebene Monsterdokument" ist der C-Standard, schau mal in die Überschrift dieses Subforums, vielleicht kommen selbst dir dann gewisse Assoziationen.

    Zorc schrieb:

    Wenn du nicht helfen kannst oder willst, was antwortest du dann überhaupt?

    Du hast keine Ahnung wovon du redest.
    Dein pubertäres Geplapper verdient nicht, hier überhaupt noch von jemandem beantwortet zu werden.
    Warum fragst du hier überhaupt, wenn du keine kompetenten und subforumskonforme Antworten verträgst?
    Ich bezweifle nach Ansicht deines Codeversuches, dass du jemals überhaupt in die Nähe meines C-Wissens kommen wirst um beurteilen zu können, ob ich helfen kann oder nicht;
    trolle dich dahin, wo du herkamst und halte den Platz für qualifizierte Frager frei oder in deinem Pubertätsjargon: "Halt einfach die Klappe".



  • OK, notiert: hier bekommt man keine Hilfe, hier werden nur aufgeblähte Egos zur Schau getragen. Soll ich jetzt ob deines angeblichen wahnsinnigen Wissens niederknien und dich anbeten?

    Hm...nein...ich weiß es: ich lasse dich und deinen kranken Geist einfach alleine. Einsamkeit dürfte ja etwas sein, was du dank deines Characters zur genüge kennst.

    PS: warum nur bestimmte Compilerversionen diesen Fehler werfen, konnte mir weder dein Ego noch dein Post noch dein verlinktes Dokument noch dein angebliches gigantomansiches Wissen beantworten.



  • In die Parameterliste der Funktionen gehört eine Ellipse ( https://de.wikipedia.org/wiki/Auslassungspunkte )

    So wie es in den Beispielen auch zu sehen ist.


  • Mod

    Zarc schrieb:

    Hi,

    ich verwende Funktionen mit variablen Parameterlisten nach folgendem Prinzip:

    static int getIntValue(const int min,const int max,va_list *vl)
    {
       int   listValue;
    
       listValue=va_arg(*vl,int);
       if (listValue<min) listValue=min;
       else if (listValue>max) listValue=max;
       return listValue;
    }
    
    unsigned long init_if_list(int *var,va_list vl)
    {
       char *listTag;
    
       listTag=va_arg(vl,char*);
       if (!strcmp(listTag,INIT_SHOWUI)) initValues.uiFlags=getIntValue(INT_MIN,INT_MAX,&vl);
    

    Das compiliert und funktioniert problemlos mit VisualStudio 201x und GCC 4.7.x oder älter. Mit dem GCC 4.8.x unter Ubuntu/64 erhalte ich folgende Fehlermeldung:

    error: cannot convert '__va_list_tag**' to '__va_list_tag (*)[1]' for argument '3' to 'int getIntValue(int, int, __va_list_tag (*)[1])'
       if (!strcmp(listTag,INIT_SHOWUI))                initValues.uiFlags=getIntValue(INT_MIN,INT_MAX,&vl);
    

    Der Grund ist etwas obskur. Wie im verlinkten Standardtext in Fußnote 253 erwähnt, ist es zulässig, einer Funktion einen Zeiger auf va_list zu übergeben damit diese mit dem gleichen va_list-Objekt weiterarbeiten kann.
    Der Standard legt allerdings NICHt fest, welche Art Typ va_list hat, insbesondere darf es sich auch um einen Arraytyp handeln.
    Das hat aber zur Folge, dass ein Funktionsparamter, der mit dem Typ va_list deklariert wurde, dann nicht tatsächlich den Typ va-list hat, wenn va_list ein Arraytyp ist. Die erwähnte Fußnote ist daher keine Lizenz dafür, ein va-list Funktionsargument per Zeiger an eine andere Funktion weiterzuleiten. Garantiert ist das nur, wenn das va_list-Objekt keinem Decay unterliegt, weil es etwa als lokales Objekt oder als Teil einer Struktur definiert wurde.
    Eine einfach Möglichkeit, den Code zu reparieren ohne an den Funktionsdeklarationen etwas ändern zu müssen wäre z.B. wie folgt:

    unsigned long init_if_list(int *var,va_list vl_param)
    {
       va_list vl;
       char *listTag;
    
       va_copy(vl, vl_param);
       listTag=va_arg(vl,char*);
       if (!strcmp(listTag,INIT_SHOWUI)) initValues.uiFlags=getIntValue(INT_MIN,INT_MAX,&vl);
    

    Warum macht gcc 4.8 nun so etwas komisches? Der Grund hat tatsächlich nichts mit der Compilerversion zu tun (kanns zwar nicht testen aber vermutlich zeigt 4.7 das gleiche Verhalten unter x86_64) sondern mit der Zielarchitektur, für die übersetzt wird. Übersetze ich folgenden Code

    #include <stdarg.h>
    
    void foo(va_list*);
    void bar(va_list ap)
    {
        foo(&ap);
    }
    

    mit gcc 4.9.3 64-bit erhalte ich den gleichen Fehler, mit -m32 verschwindet er hingegen. Der Grund ist darin zu suchen, das in der 64-bit ABI selbst Ellipsenargumente unter Umstämnden per Register übergeben werden, und die nat. nicht einfach per Zeiger erreicht werden können. Also ist hier zusätzliche Trickserei vom Compiler erforderlich. s.a. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50581#c7

    Zarc schrieb:

    Ändere ich meinen Code jetzt dahingehend ab, das va_list nicht mehr als Pointer übergeben wird:

    static int getIntValue(const int min,const int max,va_list vl)
    {
       int   listValue;
    
       listValue=va_arg(vl,int);
       if (listValue<min) listValue=min;
       else if (listValue>max) listValue=max;
       return listValue;
    }
    
    unsigned long init_if_list(int *var,va_list vl)
    {
       char *listTag;
    
       listTag=va_arg(vl,char*);
       if (!strcmp(listTag,INIT_SHOWUI)) initValues.uiFlags=getIntValue(INT_MIN,INT_MAX,vl);
    

    schmiert mir der Krempel mit VisualStudio und GCC 4.7 Code ab.

    Nicht überraschend. Vermutlich wird vl in init_if_list im nicht gezeigten Teil mit va_arg weiterverwendet, was undefiniert ist (s.o.).


Anmelden zum Antworten