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

Biblioth�ques, syst�mes et outils C Discussion :

D�finitions multiples de mes constantes de couleurs !


Sujet :

Biblioth�ques, syst�mes et outils C

  1. #1
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du pr�sident Ulysses S. Grant !
    Inscrit en
    F�vrier 2011
    Messages
    6 900
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (�le de France)

    Informations professionnelles :
    Activit� : Agent secret au service du pr�sident Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : F�vrier 2011
    Messages : 6 900
    Par d�faut D�finitions multiples de mes constantes de couleurs !
    Salut � tous.

    J'utilise une biblioth�que dans laquelle, j'ai d�clar� d'une part des fonctions et d'autre part des constantes de couleurs.
    Ma biblioth�que se nomme "libmine".

    Ce qui me pose probl�me, ce sont mes constantes. Par contre, je n'ai pas de probl�mes avec mes fonctions.
    Dans "libmine.c", j'ai mis :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    #include "libmine.h"
     
    T_COLOR         _black          = {  0,   0,   0};
    T_COLOR         _grey           = {128, 128, 128};
    T_COLOR         _white          = {255, 255, 255};
    Dans "libmine.h", j'ai mis :
    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
    #ifndef __LIBMINE__
    #define __LIBMINE__
     
    typedef struct
    {
            char    red;
            char    green;
            char    blue;
    } T_COLOR;
     
    T_COLOR         _black;
    T_COLOR         _grey;
    T_COLOR         _white;
     
    #endif
    Je compile la biblioth�que. Aucun probl�me.

    Dans le programme "main.c", j'appelle l'include :
    J'obtiens la liste suivante des messages d'erreurs :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    /usr/bin/ld*: /warehouse/Prog_C/09.Library//libmine.a(tft.o):(.data+0x808)*: définitions multiples de «*_white*»; main.o:(.bss+0x8)*: défini pour la première fois ici
    /usr/bin/ld*: /warehouse/Prog_C/09.Library//libmine.a(tft.o):(.data+0x80c)*: définitions multiples de «*_grey*»; main.o:(.bss+0x4)*: défini pour la première fois ici
    /usr/bin/ld*: /warehouse/Prog_C/09.Library//libmine.a(tft.o):(.bss+0xf0a0)*: définitions multiples de «*_black*»; main.o:(.bss+0x0)*: défini pour la première fois ici
    J'ai pourtant mis le warpper "#ifndef" afin d'�viter la duplication du contenu de "libmine.h".
    A tout hasard, je donne le makefile du main.c :
    Code Makefile : 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
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    # ------------------------------- #
    #   Déclaration des Executables   #
    # ------------------------------- #
     
    RM      = @rm -f
    CC      = @gcc
    EX      = @chmod +x
     
    # -------------------------- #
    #   Déclaration des Objets   #
    # -------------------------- #
     
    SRC     = main.c
    OBJ     = main.o
    BIN     = tft18
     
    # ---------------------------- #
    #   Déclaration des Includes   #
    # ---------------------------- #
     
    INCS    = -I"/warehouse/Prog_C/09.Library/include/"
     
    # --------------------------------- #
    #   Déclaration des Bibliothèques   #
    # --------------------------------- #
     
    LIBS    = -L"/warehouse/Prog_C/09.Library/"
     
    # ------------------------------ #
    #   Déclaration des Paramètres   #
    # ------------------------------ #
     
    FLAG    = -O -Wall -Wextra -Wpedantic
    LOAD    = -lmine -lm
     
     
    # ------------------------------------ #
    #   Compilation et Edition des liens   #
    # ------------------------------------ #
     
    all: before $(BIN) after
     
    before:
            clear
            $(RM) $(OBJ)
            $(RM) $(BIN)
     
    $(BIN): $(OBJ)
            $(CC)    $(OBJ) $(LIBS) -o $(BIN) $(LOAD)
     
    $(OBJ): $(SRC)
            $(CC) -c $(SRC) $(INCS) -o $(OBJ) $(FLAGS)
     
    after:
            $(RM) $(OBJ)
            $(EX) $(BIN)
            @./$(BIN)
    Pourquoi ai-je ce probl�me que sur les constantes ?
    Je ne comprends pas pourquoi les d�claratives de mes fonctions ne me pose aucun probl�me.

    Comment r�soudre mon probl�me ?

    Cordialement.
    Artemus24.
    @+

  2. #2
    Membre �m�rite
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activit� : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Par d�faut
    Bonjour,

    les variables globales en C � c'est parfois une plaie. Pour d�clarer des variables globales et non les d�finir il faut utiliser le mot cl� extern :

    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
    #ifndef __LIBMINE__
    #define __LIBMINE__
     
    typedef struct
    {
            char    red;
            char    green;
            char    blue;
    } T_COLOR;
     
    extern T_COLOR         _black;
    extern T_COLOR         _grey;
    extern T_COLOR         _white;
     
    #endif
    En C un peu plus moderne ou pourrait �crire :
    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
    #pragma once
     
    typedef struct {
    	unsigned char red;
    	unsigned char green;
    	unsigned char blue;
    } T_COLOR;
     
    #define _COLOR(...) ( (T_COLOR) { __VA_ARGS__ } )
    //#define _COLOR(...) ( (T_COLOR) { .red=0, .green=0, .blue=0, __VA_ARGS__ } )
     
    static inline T_COLOR _GREY_LEVEL(unsigned char n) { return _COLOR(.red=n, .green=n, .blue=n); }
    static inline T_COLOR _BLACK() { return _GREY_LEVEL(0); }
    static inline T_COLOR _GREY() { return _GREY_LEVEL(128); }
    static inline T_COLOR _WHITE() { return _GREY_LEVEL(255); }
    #pragma once peut, dans certains cas, remplacer avantageusement les include guards classiques car l'espace de nom est moins pollu�, et le compilo peut mieux optimiser les includes.
    La macro _COLOR sert � cr�er une structure anonyme bien initialis�e. Dans sa seconde forme comment�e tu peux y ajouter des valeurs par d�faut.
    Les fonctions static inline remplacent avantageusement les macros et les variables globales car elles sont tra�ables au debug, et lors d'une compilation release seront compl�tement inexistantes (sauf cas particuliers) dans le binaire. Les compilos moderne seront assez smarts pour ne pas cr�er plein de variables temporaires et dans des cas comme ceux indiqu�s utiliseront directement une structure bien initialis�e d�s le compilation time.

  3. #3
    Membre prolifique Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du pr�sident Ulysses S. Grant !
    Inscrit en
    F�vrier 2011
    Messages
    6 900
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (�le de France)

    Informations professionnelles :
    Activit� : Agent secret au service du pr�sident Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : F�vrier 2011
    Messages : 6 900
    Par d�faut
    Salut WhiteCrow.

    Merci pour les explications et les exemples.
    C'est la solution que je recherchais.

    Cordialement.
    Artemus24.
    @+

  4. #4
    Mod�rateur

    Avatar de Bktero
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par d�faut
    Tu devrais rajouter static const dans les d�clarations, pour en faire des constantes et non des variables, et r�soudre le probl�me de "mutliple definitions of".

  5. #5
    Membre �m�rite
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activit� : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Par d�faut
    const ne rend pas l'objet qualifi� constant � il ne fait qu'indiquer au compilo que l'on s'engage � ne pas le modifier, ce qui est diff�rent.

    Pour avoir de �vraies constantes� il faut soit utiliser le pr�processeur et un #define ou une fonction (�ventuellement static inline) qui renvoie toujours la m�me valeur (et que l'on pourra annoter comme const ou pure avec clang ou gcc). Dans ces cas le compilo arrive � en d�terminer la valeur au moment de la compilation. Dans le cas d'une �constante donn�e comme taille de tableau� seul un #define sera utile.

  6. #6
    Mod�rateur

    Avatar de Bktero
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par d�faut
    Ouais enfin bon...

    Ce code

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    typedef struct
    {
        char    red;
        char    green;
        char    blue;
    } T_COLOR;
     
    const T_COLOR _black = { 0, 0, 0};
     
    int main(void) {
        _black.red = 255;
    }
    l�ve une erreur :

    error: assignment of member 'red' in read-only object
    Alors, je veux bien qu'on peut caster ou faire des pointeurs incoh�rents en typage pour modifier �a (ce qui doit �tre un undefined behavior de toute fa�on), mais je pense quand m�me que c'est pas mal hein.

  7. #7
    Membre �m�rite
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activit� : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Par d�faut
    �a aurait pu �tre pas mal si cela n'avait pour cons�quence de r�pandre des const un peu partout � parce que ta variable globale (ce qui en soit n'est pas forc�ment une bonne approche) en const que tu vas passer en param�tre � une fonction qui attend un TColot mais pas const � va provoquer un warning. Alors soit, tu peux qualifier ledit param�tre en const et �a va se propages encore plus loin � ou alors tu castes et le const ne sert plus � rien. Et je ne parle pas du cas o� tu passeras un pointeur sur la variable globales �

    C n'est pas adapt� � un const de ce genre parce que const signifie r�ellement �je m'engage � ne pas modifier ce que je qualifie� mais que le compilo n'as pas la capacit� de le v�rifier ou de le contraindre.const ne permet pas de cr�er une �vraie� constante consid�r�e comme telle d�s le compilation time.
    En revanche utiliser const pour les param�tres est un peu plus utile. const c'est juste un �read only� un peu mal foutu et surtout mal compris.

    La technique de �c'est une fonction qui renvoie une valeur anonyme� permet en revanche de pallier ces nombreux probl�mes, et dans ce cas les compilo seront assez intelligents pour ne pas cr�er une pl�thore de variables temporaire ou d'appels inutiles.

  8. #8
    Mod�rateur

    Avatar de Bktero
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par d�faut
    Une fonction comme celle-ci ne provoque pas de warning, car on fait une copie :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    void print(T_COLOR c) {
        // ...
    }
    Une fonction comme celle-ci en revanche en g�n�rera un :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    void print(T_COLOR* c) {
        // ...
    }
    Il faut effectivement faire :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    void print(const T_COLOR* c) {
        // ...
    }
    Ce qui permet alors de faire :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    int main(void) {
        print(&_black);
    }
    Je veux bien qu'on soit en C et que je ne fais plus que du C++, mais pour moi, on est vraiment dans un cas typique de donn�es constantes. La propagation des const est l� pour �a. C'est le but m�me.

    Tu n'utilises jamais const en C ?

  9. #9
    Membre �m�rite
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activit� : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Par d�faut
    Jamais pour d�finir une constante car const ne permet pas de le faire et n'est pas fait pour �a d'ailleurs.

    Imagine simplement qu'un champ de structure soit de type T_Color
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    typedef struct {
        T_Point *center;
        double radius;
        T_Color *color;
    } T_Circle;
    Imagine en plus que tu aimes tellement les const et les variables globales qu'on retrouve quelque part dans le code :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
     
    const T_Point _Origin = (T_Point) {.x=0, .y=0};

    Tu auras le choix soit d'utiliser tes const globales (en les castant) pour cr�er de nouveaux objets avec la possibilit� de bug et modification non voulue desdites const globales, soit de copier les valeurs des const globales dans les primitives de cr�ation.
    Du coup �a va s�v�rement limiter l'utilit� du const.
    En revanche si tu as un simple #define ou une fonctions static inline qui renvoie un objet tu te lib�res de ces soucis. Dans ces cas tu as directement un litt�ral optimisable lors des phases compilation et d'�dition des liens. Dans ton cas tu t'exposes � des bugs au runtime.

    Alors const, �mha, n'est r�ellement utile que pour qualifier un param�tre de fonction afin d'indiquer au compilo que tu t'engages � ne pas le modifier et qu'il peut all�grement faire toutes les optimisations qui lui sont permises. Bon si tu lui mens, tu te tire une balle dans le pied.
    C'est un peu comme restrict � dans les deux cas c'est un contrat que tu passes avec ton compilo.

  10. #10
    Mod�rateur

    Avatar de Bktero
    Homme Profil pro
    Ing�nieur d�veloppement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activit� : Ing�nieur d�veloppement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par d�faut
    Tu auras le choix soit d'utiliser tes const globales (en les castant)
    Il faut arr�ter avec �a : https://wiki.sei.cmu.edu/confluence/...+qualification

    Do not cast away a const qualification on an object of pointer type. Casting away the const qualification allows a program to modify the object referred to by the pointer, which may result in undefined behavior. See undefined behavior 64 in Appendix J of the C Standard.
    Ces m�mes guidelines recommandent d'ailleurs d'utiliser const. Voir https://wiki.sei.cmu.edu/confluence/...literal+values ou https://wiki.sei.cmu.edu/confluence/...utable+objects

    Il est d'ailleurs que c'est normal que �a se propage (citation du 2e lien) :

    Adding const qualification may propagate through a program; as you add const, qualifiers become still more necessary. This phenomenon is sometimes called const poisoning, which can frequently lead to violations of EXP05-C. Do not cast away a const qualification. Although const qualification is a good idea, the costs may outweigh the value in the remediation of existing code
    Commencer � mettre des const oblige � r�fl�chir tr�s fortement � ses types. Et oui, c'est contraignant. Parfois peut-�tre trop, surtout dans une base de code existante.

    Ton exemple est incomplet � mon avis pour illustrer compl�tement ce que tu veux dire :

    - Pourquoi ta classe T_CIRCLE a besoin de pointer sur une couleur non constante ?
    - Est-ce que tu ne pourrais pas utiliser une couleur constante ?
    - Qu'est ce que �a apporterait comme b�n�fice ou inconv�nient ?
    - Pourquoi un pointeur d'ailleurs ?

    De plus, comment vas-tu faire matcher un pointeur sur T_COLOR avec un #define d'un T_COLOR ? M�me question avec le retour d'une fonction (quelle soit static inline ou pas).

  11. #11
    Membre �m�rite
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activit� : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Par d�faut
    Citation Envoy� par Bktero Voir le message
    Citation Envoy� par WhiteCrow Voir le message
    Tu auras le choix soit d'utiliser tes const globales (en les castant)
    Il faut arr�ter avec �a : [�]
    Je veux bien que tu exhibes tous les liens que tu veux, mais prends au moins toute mon argumentation en compte � parce que non seulement il y a un si avant mais aussi un soit apr�s.

    Citation Envoy� par WhiteCrow Voir le message
    Imagine que [=si] [suit un exemple o� on utilise un pointeur sur un objet dont le type point� est le type de la constante]

    Tu auras le choix soit d'utiliser tes const globales (en les castant) pour cr�er de nouveaux objets avec la possibilit� de bug et modification non voulue desdites const globales, soit de copier les valeurs des const globales dans les primitives de cr�ation.
    Donc, peut-�tre plus clairement, si on opte pour un tel design par exemple :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    include <stdio.h>
     
    struct color {
    	double R;
    	double G;
    	double B;
    };
     
    static const struct color _WHITE = (const struct color) {.R=1.0, .G=1.0, .B=1.0 };
     
    struct what_ever {
    	struct color *pcolor;
    	// …
    };
    Alors pour donner une valeur au champ pcolor en utilisant �la constante� on a le choix entre :
    • soit caster (pour faire taire un warning)
      Code : S�lectionner tout - Visualiser dans une fen�tre � part
      1
      2
      	//struct what_ever foo = (struct what_ever) {.pcolor=&_WHITE};
      	struct what_ever foo = (struct what_ever) {.pcolor=(struct color *)&_WHITE};
      et, comme je le notais, cela intriduit une �possibilit� de bug et modification non voulue desdites const globales
    • soit copier (pour oublier un const qui n'avait pas lieu d'�tre en premier lieu car mal utilis�, �mha)
      Code : S�lectionner tout - Visualiser dans une fen�tre � part
      struct what_ever bar = (struct what_ever) {.pcolor= (struct color[]) {_WHITE} };
      qui alourdit le code.



    Citation Envoy� par Bktero Voir le message
    Ton exemple est incomplet � mon avis pour illustrer compl�tement ce que tu veux dire :

    - Pourquoi ta classe T_CIRCLE a besoin de pointer sur une couleur non constante ?
    - Est-ce que tu ne pourrais pas utiliser une couleur constante ?
    - Qu'est ce que �a apporterait comme b�n�fice ou inconv�nient ?
    - Pourquoi un pointeur d'ailleurs ?

    De plus, comment vas-tu faire matcher un pointeur sur T_COLOR avec un #define d'un T_COLOR ? M�me question avec le retour d'une fonction (quelle soit static inline ou pas).
    Alors dans l'ordre :
    • Pourquoi ta classe T_CIRCLE a besoin de pointer sur une couleur non constante ?
      Mon exemple pr�c�dent est sans doute plus parlant et n'introduit plus de distractions.

    • Est-ce que tu ne pourrais pas utiliser une couleur constante ?
      Es-tu en train de me dire que le const poisoning devrait aller jusqu'� rendre const tous les champs d'une structure dont le type serait celui d'une constante ?

    • Qu'est ce que �a apporterait comme b�n�fice ou inconv�nient ?
      heu � � quoi ?

    • Pourquoi un pointeur d'ailleurs ?
      Dans le cadre de l'exemple avec le cercle, pour partager la couleur entre plusieurs cercles � mais � la limite pourquoi pas ? le const poisoning interdirait-il l'utilisation de pointeurs sur un type pour lequel on aurait d�finit des constantes ?

    • De plus, comment vas-tu faire matcher un pointeur sur T_COLOR avec un #define d'un T_COLOR ? M�me question avec le retour d'une fonction (quelle soit static inline ou pas).
      De la m�me mani�re que je copie une �constante globale (ou non) statique (ou non)� dans un objet anonyme dont je prends l'adresse.
      Code : S�lectionner tout - Visualiser dans une fen�tre � part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      #define WHITE ((struct color) {.R=1.0, .G=1.0, .B=1.0})
       
      struct color white(void) {
      	return WHITE;
      }
       
      ...
       
      	struct what_ever baz = (struct what_ever) {.pcolor= (struct color[]) {WHITE} };
      	struct what_ever qux = (struct what_ever) {.pcolor= (struct color[]) {white()} };
      …
      Le static inline ne sert qu'� aider le compilo � optimiser les appels. C'est un moyen comme un autre �d'avoir des macros typ�es�.


    Maintenant, tr�s personnellement et de but en blanc, j'opterais sans doute pour une API plus proche de :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    enum color_index { DEFAULT=0, BLACK=DEFAULT, /* ... */, WHITE };
     
    struct color color_RGB(double, double, double);
    struct color color_index(enum color_index index);
    // ....
     
    struct color *color_alloc(void);
    struct color *color_free(const struct color *);
    Tu remarqueras que je suis la const correctness avec ma fonction de lib�ration de la m�moire d'un struct color* car lib�rer de la m�moire allou�e ne modifie pas/ne devrait pas modifier ce qui est point� � mais que cela va poser des probl�mes (sans doute) avec le free qui lui, dans sa version standard, n'a pas ce qualificateur au param�tre � un �cast obligatoire en l'occurrence� qui indique bien la diff�rence entre �const qui qualifierait une vraie constante� et �const qui indique au compilo qu'on s'engage � ne pas modifi� ce qui est qualifi�.

  12. #12
    R�dacteur/Mod�rateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 153
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 38
    Localisation : Canada

    Informations professionnelles :
    Activit� : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par d�faut
    Citation Envoy� par WhiteCrow Voir le message
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    include <stdio.h>
     
    struct color {
    	double R;
    	double G;
    	double B;
    };
     
    static const struct color _WHITE = (const struct color) {.R=1.0, .G=1.0, .B=1.0 };
     
    struct what_ever {
    	struct color *pcolor;
    	// …
    };
    Alors pour donner une valeur au champ pcolor en utilisant �la constante� on a le choix entre :
    • soit caster (pour faire taire un warning)
      Code : S�lectionner tout - Visualiser dans une fen�tre � part
      1
      2
      	//struct what_ever foo = (struct what_ever) {.pcolor=&_WHITE};
      	struct what_ever foo = (struct what_ever) {.pcolor=(struct color *)&_WHITE};
      et, comme je le notais, cela intriduit une �possibilit� de bug et modification non voulue desdites const globales
    • soit copier (pour oublier un const qui n'avait pas lieu d'�tre en premier lieu car mal utilis�, �mha)
      Code : S�lectionner tout - Visualiser dans une fen�tre � part
      struct what_ever bar = (struct what_ever) {.pcolor= (struct color[]) {_WHITE} };
      qui alourdit le code.
    Ou alors, un peu de bon sens
    - se rendre que const est un mot-cl� qui existe pour une tr�s bonne raison et tout comme on n'est pas senc� ignorer les warnings, on va pas l'ignorer non plus
    - soit tu mets ton pointeur const, parce que tu utilises des couleurs pr�d�finies, partag�es, et n'es donc pas senc� les modifier
    - soit la couleur est une copie dans chaque cercle qui en fait ce qu'il veut, et la constante peut �tre utilis�e comme valeur source � recopier

    Parce que bon justifier que le marteau est un mauvais outil parce qu'on peut pas visser avec, c'est un peu gros.
    Et si tu aimes tant tout caster et casser, pourquoi s'emmerder � utiliser des types alors qu'on pourrait tout mettre void* puis caster partout n'importe comment quand on veut ?

    Donc de ce que tu dis :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    struct what_ever bar = (struct what_ever) {.pcolor= (struct color[]) {_WHITE} };
    Alourdit le code
    mais
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct color white(void) {
    	return WHITE;
    }
     
    ...
     
    	struct what_ever baz = (struct what_ever) {.pcolor= (struct color[]) {WHITE} };
    	struct what_ever qux = (struct what_ever) {.pcolor= (struct color[]) {white()} };
    …
    est totalement ok
    Et assigner � un pointeur un truc � partir d'un define, ou d'une copie retourn�e par une fonction, donc temporaire, est au mieux cavalier.

    Et encore une fois c'est juste ton constat de d�part qui est faux parce que soit tu utilises des constantes et n'as pas � les modifier, soit tu les utilises pour cr�er des copies et tu en fais ce que tu veux.
    Si tu utilises les constantes, tu peux les partager et utiliser les pointeurs pour �a, mais si tu comptes en faire des copies, c'est l'utilisation de pointeurs qui devrait �tre remis en cause.

    lib�rer de la m�moire allou�e ne modifie pas/ne devrait pas modifier ce qui est point�
    T'es s�r que tu es toujours en C ?
    Parce que lib�rer un pointeur, �a rend juste totalement invalide l'objet point�, ce qui est une modification assez cons�quente dudit objet.
    Pensez � consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation r�seau ?
    Aucune aide via MP ne sera dispens�e. Merci d'utiliser les forums pr�vus � cet effet.

  13. #13
    Membre �m�rite
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Juillet 2020
    Messages
    352
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activit� : Chef de projet NTIC

    Informations forums :
    Inscription : Juillet 2020
    Messages : 352
    Par d�faut
    Citation Envoy� par Bousk Voir le message
    Ou alors, un peu de bon sens
    - se rendre que const est un mot-cl� qui existe pour une tr�s bonne raison et tout comme on n'est pas senc� ignorer les warnings, on va pas l'ignorer non plus
    - soit tu mets ton pointeur const, parce que tu utilises des couleurs pr�d�finies, partag�es, et n'es donc pas senc� les modifier
    - soit la couleur est une copie dans chaque cercle qui en fait ce qu'il veut, et la constante peut �tre utilis�e comme valeur source � recopier

    Parce que bon justifier que le marteau est un mauvais outil parce qu'on peut pas visser avec, c'est un peu gros.
    Et si tu aimes tant tout caster et casser, pourquoi s'emmerder � utiliser des types alors qu'on pourrait tout mettre void* puis caster partout n'importe comment quand on veut ?
    Historiquement const a �t� introduit trop rapidement en C, le WG14 ayant, toujours �mha, voulu trop c++ifier le c � il suffit de d'essayer d'�tre const correct et d'utiliser ne serait-ce qu'avec strcpy.
    Tu proposes d'autres design � soit. Mais ce n'est pas parce qu'il en existe d'autres que �a va faire avancer le schmilblick � ce n'est pas parce que tu n'as qu'un tournevis qu'il faut mettre des vis partout �
    Ensuite, comprends bien que je ne dis pas que c'est une bonne chose de caster � tour de bras, bien au contraire. Ce que je dis (et relis moi bien s'il te pla�t) est qui si l'on opte pour ce design alors on aura soit le choix de caster soit le choix de copier � tour de bras �

    En tr�s clair : c'est un mauvais design, entre autre d� cette utilisation particuli�re de const qui n'est pas adapt�e car il y a un d�calage entre ce qu'est une constante en C et la similarit� du mot �constante� et du mot cl� const.
    Quant � la justification �c'est un mot cl� qui existe et qui dont a une utilit� et donc on va l'utiliser� permet moi de te demander si tu utilises tout autant goto, auto, ou register ? Je ne pense pas (mais je peux me tromper hein).

    Ce que je dis avant tout est qu'il faut utiliser const l� o� c'est utile (tout comme volatile ou restrict ou goto ou dans un futur plus moins proche auto.

    Citation Envoy� par Bousk Voir le message
    Donc de ce que tu dis :

    Alourdit le code
    mais

    est totalement ok
    Et assigner � un pointeur un truc � partir d'un define, ou d'une copie retourn�e par une fonction, donc temporaire, est au mieux cavalier.
    � nouveau, remets tout �a dans le contexte que tu as cr�� : tu me demandes comment on fait, je te montre comment on fait. Il ne faut y voir �une bonne pratique que je recommanderai�, bien au contraire. Que ce soit l'utilisation de const ou de #define ou d'une fonction, le design est mal foutu et �a va alourdir le code � m�me si c'est du C moderne.
    Je ne d�fends pas cette solution, ce que tu peux ais�ment comprendre en lisant mon message jusqu'au bout et en constatant que ce vers quoi je tendrai de but en blanc en premier jet est tout autre chose �

    Citation Envoy� par Bousk Voir le message
    Et encore une fois c'est juste ton constat de d�part qui est faux parce que soit tu utilises des constantes et n'as pas � les modifier, soit tu les utilises pour cr�er des copies et tu en fais ce que tu veux.
    Si tu utilises les constantes, tu peux les partager et utiliser les pointeurs pour �a, mais si tu comptes en faire des copies, c'est l'utilisation de pointeurs qui devrait �tre remis en cause.


    T'es s�r que tu es toujours en C ?
    Parce que lib�rer un pointeur, �a rend juste totalement invalide l'objet point�, ce qui est une modification assez cons�quente dudit objet.
    lol bien s�r � il suffit de comprendre ce que const signifie quand il qualifie un param�tre � et ce qu'est une lib�ration de m�moire.
    Est-ce que le fait de lib�rer la m�moire modifie ce qui est point� ? non.
    Est-ce que je peux qualifier de const quelque chose qui ne sera pas modifi� ? oui, c'est meme le but d'�tre const correct ; mais tu m'arr�teras sur ce point si je me trompe.
    Est-ce que je devrais faire taire un warning dans ce cas ? oui, car free n'est pas const correct ; tout comme une flopp�e d'autres fonctions standards (je citai strcpy un peu plus haut mais il y en a d'autres �)

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. probl�me avec mes constantes
    Par salseropom dans le forum C
    R�ponses: 6
    Dernier message: 10/05/2006, 17h37
  2. D�finition multiple
    Par Goundy dans le forum C
    R�ponses: 7
    Dernier message: 02/04/2006, 18h59
  3. d�finition multiple
    Par elekis dans le forum C++
    R�ponses: 3
    Dernier message: 01/03/2006, 16h32
  4. [g++] D�finitions multiples
    Par GLDavid dans le forum Autres �diteurs
    R�ponses: 4
    Dernier message: 12/12/2005, 16h04
  5. R�ponses: 22
    Dernier message: 05/07/2005, 00h04

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