IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

[gcc 7.5.0] structure avec des champs éronnés


Sujet :

C

  1. #1
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut [gcc 7.5.0] structure avec des champs éronnés
    Bonsoir,

    Je vous dis tout de suite, je suis fatigué, et je n'ai plus l'esprit très clair...

    Voici mon soucis: j'ai fait une librairie qui inclut la structure suivante...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    struct s_RGB
    {
      unsigned short Red;
      unsigned short Green;
      unsigned short Blue;
      bool  bold;
      unsigned short alpha;  // facilite la gestion de la transparence en SDL2 
    };
    Ce qui est assez étonnant c'est que la valeur de "bold" est toujours 0, que je mette true ou 1 :{

    ...dans un programme je fais ceci:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    void ShowMe(void *ItsMe)
    {
    	t_Ennemy *tmp=(t_Ennemy*)ItsMe;
    	switch(tmp->Defeats)
    	{
    		case 2:		setForegroundColor((struct s_RGB){170,255,0,true,0});
    							break;
    		case 3:   setForegroundColor((struct s_RGB){85,255,255,true,0});
    							break;
    		case 4:		setForegroundColor((struct s_RGB){255,255,0,true,0});
    							break;
    		case 5:		setForegroundColor((struct s_RGB){255,151,82,true,0});
    							break;
    		case 6:		setForegroundColor((struct s_RGB){235,133,49,true,0});
    							break;
    		default:	setForegroundColor((struct s_RGB){255,255,255,false,0});
    							break;
     
    	}
    	wprintf(L"\t%s [%02d]\n",tmp->pName,tmp->Defeats);
    	setForegroundColor((struct s_RGB){255,255,255,false,0});
    }
    ...cette fonction est appelée dans une librairie comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    void lc_showList(ListeChainee *pListe)
    {
    	if(pListe==NULL) return;
    	if(pListe->pHead!=NULL)
    	{
    		lc_Datas *lc_parcours=pListe->pHead;
      
    		while(lc_parcours!=NULL)
    		{
    			if(lc_parcours->pDisplay!=NULL) lc_parcours->pDisplay(lc_parcours->value);
    			
    			lc_parcours=lc_parcours->pNext;
    			fflush(stdout);
    		}
    	}
    }
    ...dans mon programme je mets tout en place ici...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
                            if(found==-1) 
    			{
    				unsigned short us_ID=lc_insert((void*)Ennemi,ll_Ennemis,cssmuserdef,sizeof(t_Ennemy));
    				lc_setDisplayByID(ll_Ennemis,us_ID,ShowMe);
    			}
    ... lc_setDisplayByID() est la fonction qui permet de spécifier quelle sera la fonction pour afficher l'élément de la liste chaînée si besoin est...

    Dans la librairie j'ai placé des instructions de "debug"...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void setForegroundColor(struct s_RGB color)
    {
    	wprintf(L"[%s] DEBUG --> %d;%d;%d %d (%d)\n",__func__,color.Red,color.Green,color.Blue,color.bold,color.alpha);
     
    	char *couleurAvantPlan=getRGBString(color);
    	wprintf(L"%s",couleurAvantPlan);
    	free(couleurAvantPlan);
    }
    ...et aussi...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    char* getRGBString(struct s_RGB target)
    {
    	wprintf(L"\n[DEBUG] %d;%d;%d %d (%d)\n",target.Red,target.Green,target.Blue,target.bold,target.alpha);
     
    	char *pTmp=(char*)malloc(sizeof(char)*25); // \x1b[38;2;74;213;237;1m
    	memset(pTmp,0,25);
     
    	sprintf(pTmp,"\x1b[38;2;%d;%d;%d%sm",target.Red,target.Green,target.Blue,target.bold?";1":"");
    	return pTmp;
    }
    ...quand j'exécute mon programme j'ai TOUJOURS 0 dans le champs "bold" :{

    J'ai fait un petit programme de test qui n'utilise pas la librairie...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #include <stdio.h>
    #include <stdbool.h>
     
    struct s_RGB
    {
        short R;
        short G;
        short B;
        bool bold;
        short alpha;
    };
     
    void testRGB(struct s_RGB);
     
    void main(void) // PAS ANSI mais je m'en fous
    {
        struct s_RGB test=(struct s_RGB){170,255,0,true,0};
        printf("%d,%d,%d %d (%d)\n",test.R,test.G,test.B,test.bold,test.alpha);
        testRGB((struct s_RGB){170,255,0,true,0});
    }
     
    void testRGB(struct s_RGB target)
    {
        printf("%s %d,%d,%d %d (%d)\n",__func__,target.R,target.G,target.B,target.bold,target.alpha);
    }
    ...là ça fonctionne, bold a une valeur à 1 (true)...

    Le même programme avec la librairie donne 1 au champs "bold" :]

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #include <stdio.h>
    #include <uep_wide.h>
     
    void testRGB(struct s_RGB);
     
    void main(void)
    {
        struct s_RGB test=(struct s_RGB){170,255,0,true,0};
        printf("%d,%d,%d %d (%d)\n",test.Red,test.Green,test.Blue,test.bold,test.alpha);
        testRGB((struct s_RGB){170,255,0,true,0});
    }
     
    void testRGB(struct s_RGB target)
    {
        printf("%s %d,%d,%d %d (%d)\n",__func__,target.Red,target.Green,target.Blue,target.bold,target.alpha);
    }
    sirius:/exemples/structures # gcc debugRGBwithuepwide.c `pkg-config uepwide --cflags` `pkg-config uepwide --libs` -o debugRGBwithuepwide
    sirius:/exemples/structures # ./debugRGBwithuepwide
    170,255,0 1 (0)
    testRGB 170,255,0 1 (0)
    sirius:/exemples/structures #

    Qu'est-ce que j'ai mal fait dans mon programme alors ???
    Je sais pas super bien utiliser gdb avec un programme qui prends des paramètres en ligne de commande sinon je ferais bien un "watch" pour voir si -- comme par hasard -- je ne me taperais pas une saloperie d'effet de bord...

    [edit added png]
    Nom : bug202201_000.png
Affichages : 252
Taille : 56,8 Ko
    [edit]
    Là je sais pas...

  2. #2
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Corrections effectuées, car apparemment ANSI ne permet pas de changer la couleur d'affichage ET le mode gras.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    char* getRGBString(struct s_RGB target)
    {
    	char *pTmp=(char*)calloc(25,sizeof(char)); // \x1b[38;2;xxx;xxx;xxxm 
    	sprintf(pTmp,"\x1b[38;2;%d;%d;%dm",target.Red,target.Green,target.Blue);
    	return pTmp;
    }
     
    char* getReverseRGBString(struct s_RGB target)
    {
    	char *pTmp=(char*)calloc(25,sizeof(char)); // \x1b[48;2;xxx;xxx;xxxm 
           sprintf(pTmp,"\x1b[48;2;%d;%d;%dm",target.Red,target.Green,target.Blue);
    	return pTmp;
    }
     
    void setForegroundColor(struct s_RGB color)
    {
    	char *couleurAvantPlan=getRGBString(color);
    	if(color.bold) wprintf(L"\x1b[1m");
    	else wprintf(L"\x1b[0m");
    	wprintf(L"%s",couleurAvantPlan);
    	fflush(stdout);
    	free(couleurAvantPlan);
    }
    Ceci est plus correct au niveau ANSI mais cela ne m'explique toujours pas pourquoi la valeur du champs "bold" de la structure n'est pas passé dans ce programme alors que dans un autre programme... il l'est...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #include <stdio.h>
    #include <uep_wide.h>
     
    void main(void)
    {
        InitUEPWIDE("fr_BE.utf8");
     
        struct s_RGB test=(struct s_RGB){170,255,0,true,0};
        wprintf(L"%d,%d,%d %d (%d)\n",test.Red,test.Green,test.Blue,test.bold,test.alpha);
        // testRGB((struct s_RGB){170,255,0,true,0});
     
        setForegroundColor(test);
        wprintf(L"Un texte...\n");
        setForegroundColor((struct s_RGB){180,180,180,true});
        wprintf(L"Un autre texte gras...\n");
        setForegroundColor((struct s_RGB){180,180,180,false});
        wprintf(L"Un autre texte non gras...\n");
    		setForegroundColor((struct s_RGB){170,255,0,false,0});
        wprintf(L"Un texte non gras...\n");
        wprintf(L"\x1b[0m");
     
    }
    Nom : bug202201_001.png
Affichages : 234
Taille : 10,8 Ko

  3. #3
    Membre expérimenté
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Points : 1 376
    Points
    1 376
    Par défaut
    Hello,
    ton problème est particulier …
    Dans ton log gdb je vois que tu appelles la fonction setForegroundColor avec le compound literal (struct s_RGB){170,255,0,true,0} et qu'en faisant un simple step le champ bold passe de true (si true vaut bien 1) à 0 dans la copie passée en paramètre …

    Tu compiles avec une option d'optimisation aggressive (genre -O3) ?

    Sinon, avec gdb pour passer des paramètres à ton programme il suffit de les donner à la commande run :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ gdb ./mon_programme
    ... blablabla ...
    $ run arg1 arg2 -option1 -option2 arg3
    …
    ou d'utiliser la commande set argsdoc gdb.

  4. #4
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Oui merci Whitecrow, j'ai pensé à ça aussi (-O3) mais même sans j'observe le même phénomène...
    Je suis en train d'essayer de debugger en regardant l'état de la pile mais c'est galère, l'assembler et moi on est copains mais je suis pas du tout un expert.

    Concernant gdb j'ai retrouvé des notes, ça va je sais comment m'en tirer avec gdb et un programme acceptant des paramètres en ligne de commande.

    [EDIT]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    #ifndef _STDBOOL_H
    #define _STDBOOL_H
    
    #ifndef __cplusplus
    
    #define bool	_Bool
    #define true	1
    #define false	0
    
    #else /* __cplusplus */
    
    /* Supporting _Bool in C++ is a GCC extension.  */
    #define _Bool	bool
    
    #if __cplusplus < 201103L
    /* Defining these macros in C++98 is a GCC extension.  */
    #define bool	bool
    #define false	false
    #define true	true
    #endif
    
    #endif /* __cplusplus */
    
    /* Signal that all the definitions are present.  */
    #define __bool_true_false_are_defined	1
    
    #endif	/* stdbool.h */
    Il y a quelque chose de similaire dans ma librairie

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #ifndef bool
    typedef enum {false,true}bool;
    #define bool bool
    #endif
    Mais "bool" est défini donc le typedef enum n'est pas pris en compte par le pré-processeur.

  5. #5
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Voilà: j'ai viré le #include <stdbool.h> de mon programme, j'ai laissé ma librairie définir le type "bool" et le tour est joué...

    Nom : bug202201_004.png
Affichages : 220
Taille : 7,6 Ko

    Nom : bug202201_005.png
Affichages : 217
Taille : 60,0 Ko

    ...maintenant expliquer pourquoi stdbool.h (c++) foutrait le bor**l là dedans, je l'ai utilisé mille fois ce fichier d'en-tête et je n'ai jamais rencontré de soucis...

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Citation Envoyé par hurukan Voir le message
    stdbool.h (c++)
    Le type bool existe en C++, mais pas en C.

    En C, il faut utiliser 1 type unsigned char et les valeurs 0 et 1 (au moins).
    Depuis le C99, le type bool a été introduit ... avec des macros.
    <cstdbool> (stdbool.h), documentation en anglais

  7. #7
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Oui foetus j'avais vérifié si bool était défini... comme il l'était j'avais mis ça de côté, d'autant plus qu'il n'y avait aucun warning ni erreur à la compilation...


    Nom : bug202201_006.png
Affichages : 221
Taille : 45,5 Ko

  8. #8
    Membre expérimenté
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Points : 1 376
    Points
    1 376
    Par défaut
    Citation Envoyé par foetus Voir le message
    Le type bool existe en C++, mais pas en C.

    En C, il faut utiliser 1 type unsigned char et les valeurs 0 et 1 (au moins).
    Depuis le C99, le type bool a été introduit ... avec des macros.
    <cstdbool> (stdbool.h), documentation en anglais
    C99 a introduit le type _Bool (scalaire avec pour seules valeurs 0 et 1). Le header stdbool.h définit des macros pour bool, true et false. Par défaut, gcc 7 compile C en mode gnu11, soit C11 avec les extensions GNU.

  9. #9
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Citation Envoyé par hurukan Voir le message
    ...maintenant expliquer pourquoi stdbool.h (c++) foutrait le bor**l là dedans, je l'ai utilisé mille fois ce fichier d'en-tête et je n'ai jamais rencontré de soucis...
    Il n'y a pas de raison que le type bool soit le problème. En le remplaçant par un enum tu as juste changé sa taille le faisant passer d'1 à celle d'un int. Je crains qu'il n'y ait un vérolage quelque part et que le changement de taille l'aurait juste déplacé.
    Tu peux essayer de donner au true de ton enum la valeur -1, et vérifier qu'à l'arrivée tu as bien encore -1 et pas une autre valeur non nulle. Dans tous les cas, il va falloir débuguer.

  10. #10
    Membre averti

    Homme Profil pro
    Enseignant
    Inscrit en
    Septembre 2012
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Septembre 2012
    Messages : 313
    Points : 354
    Points
    354
    Par défaut
    Dans /usr/include/stdbool.h true et false sont des entiers aussi et non des unsigned char de 1 octet...
    Je suis en train de bosser dès que je rentre je regarde avec gdb ce qu'il y a dans la pile au moment des différents appels de fonction.
    Je pensais à un effet de bord mais en "débuggant" la valeur de "bold" changeait uniquement lorsque j'entrais dans une fonction et que je copiais les valeurs dans une autre variable locale.

  11. #11
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Citation Envoyé par hurukan Voir le message
    Dans /usr/include/stdbool.h true et false sont des entiers aussi et non des unsigned char de 1 octet...
    Je suis en train de bosser dès que je rentre je regarde avec gdb ce qu'il y a dans la pile au moment des différents appels de fonction.
    Je pensais à un effet de bord mais en "débuggant" la valeur de "bold" changeait uniquement lorsque j'entrais dans une fonction et que je copiais les valeurs dans une autre variable locale.
    Dans stdbool.h le type bool est _Bool qui a normalement la même taille que char. Les valeur 1 et 0 sont converties en _Bool donc ce ne sont pas des int.
    Tu peux vérifier en faisant sizeof(struct s_RGB), selon moi elle fait 2+2+1(+1)+2=8 octets avec _Bool et devrait faire 2+2+4+2(+2)=12 octets en supposant que les enum sont créés comme des int (ça dépend du compilo) qui ferait alors 4 octets.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 26/04/2006, 08h53
  2. probleme avec des champs numeriques
    Par el_quincho dans le forum Access
    Réponses: 1
    Dernier message: 16/03/2006, 11h55
  3. [SELECT] Faire un select avec des champs vides
    Par MinsK dans le forum Langage SQL
    Réponses: 1
    Dernier message: 09/08/2005, 00h05
  4. Between avec des champs de tables
    Par talggir dans le forum Langage SQL
    Réponses: 3
    Dernier message: 24/05/2005, 09h11
  5. [word] Generer un document avec des champs
    Par webbulls dans le forum Bases de données
    Réponses: 3
    Dernier message: 29/04/2004, 10h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo