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 :

static ou pas static ?


Sujet :

C

  1. #1
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 711
    Points : 31 028
    Points
    31 028
    Billets dans le blog
    1
    Par défaut static ou pas static ?
    Bonjour à tous

    J'ai été confronté récemment à une interrogation à propos de la nécessité du static. Le problème (réduit à son minimum) était le remplissage d'un tableau de pointeurs pris à partir d'un autre tableau.
    Voici le code minimal (et compilable) d'illustration

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdio.h>
     
    void remplir(char *tab[]) {
    	static char *orig[]={"toto", "titi", "tata"};
    	for (int i=0; i < 3; i++) tab[i]=orig[i];
    }
     
    int main() {
    	char *tab[3];
    	remplir(tab);
    	for (int i=0; i < 3; i++) printf("tab[%d]=%s\n", i, tab[i]);
    }

    Je suis donc parti de l'idée que le tableau de remplissage (ici "orig") devait être static pour qu'il perdure au delà de la fonction et que les pointeurs copiés dans "tab" soient toujours valides même après avoir quitté la fonction.
    Puis, j'ai été pris d'un doute. En effet, ce n'est pas "orig" qui importe, mais son contenu. Et ce contenu, lui, provient de la zone (je ne me souviens plus son nom) qui contient les strings écrites en dur, exactement comme quand on écrit char *nom="toto". Bref, ayant sauvegardé les adresses de ces 3 strings dans "tab", adresses qui, elles restent inaliénable, que "orig" reste ou disparaisse importe peu.

    Voilà l'objet de mon questionnement. Le tableau "orig" nécessite-t-il de rester en static ou pas ? Accessoirement sans "static" ça compile et ça fonctionne aussi.

    Merci à tous.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 639
    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 639
    Points : 10 593
    Points
    10 593
    Par défaut
    Je dois vérifier mes dires mais static a avoir avec la portée d'1 variable et sa durée de vie. Et donc tu dois avoir 3 cas :
    • dans 1 fonction
    • dans 1 fichier .c/ .cpp en variable globale
    • dans 1 classe (en C++ seulement)


    Dans 1 fonction, static veut dire que cette variable n'est accessible que dans cette fonction et est initialisée 1 seule fois.
    Le code classique universitaire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    size_t yield_value() {
        static size_t value = 0;
     
        return ++value;
    }
     
    // ...
     
        printf("%lu %lu\n", yield_value(), yield_value()); // 1 2
        printf("%lu %lu\n", yield_value(), yield_value()); // 3 4
    Donc avec 1 tableau, ton tableau ne sera pas recréé à chaque appel : pour 3 valeurs c'est cacahuète ... à moins d'être dans 1 contexte embarqué.

  3. #3
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 711
    Points : 31 028
    Points
    31 028
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par foetus Voir le message
    Je dois vérifier mes dires mais static a avoir avec la portée d'1 variable et sa durée de vie.
    Exact. Donc ici, mon "orig" perdure au delà de la fin de fonction. Sauf que ce n'est pas "orig" qui m'importe, c'est son contenu...

    Citation Envoyé par foetus Voir le message
    Dans 1 fonction, static veut dire que cette variable n'est accessible que dans cette fonction et est initialisée 1 seule fois.
    Exact. Initialisée une seule fois, mais accessible chaque fois qu'on retourne dans la fonction. Ton code effectivement est classique pour illustrer ce fait

    Citation Envoyé par foetus Voir le message
    Donc avec 1 tableau, ton tableau ne sera pas recréé à chaque fois : pour 3 valeurs c'est cacahuète
    Malheureusement tu ne réponds pas à la question (le nb de valeurs, 3 ou 300, n'entre pas en ligne de compte ici car il n'est là que pour montrer un code d'exemple). La question, c'est "avec ou sans static, est-ce que les pointeurs que j'ai copiés dans tab continuent à pointer vers "toto", "titi" et "tata". Ou (dans l'autre sens), est-ce que "toto", "titi" et "tata" sont conservés dans la zone où il y a toutes les strings en dur...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    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 Sve@r Voir le message
    Bonjour à tous

    J'ai été confronté récemment à une interrogation à propos de la nécessité du static. Le problème (réduit à son minimum) était le remplissage d'un tableau de pointeurs pris à partir d'un autre tableau.
    Voici le code minimal (et compilable) d'illustration

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdio.h>
     
    void remplir(char *tab[]) {
    	static char *orig[]={"toto", "titi", "tata"};
    	for (int i=0; i < 3; i++) tab[i]=orig[i];
    }
     
    int main() {
    	char *tab[3];
    	remplir(tab);
    	for (int i=0; i < 3; i++) printf("tab[%d]=%s\n", i, tab[i]);
    }

    Je suis donc parti de l'idée que le tableau de remplissage (ici "orig") devait être static pour qu'il perdure au delà de la fonction et que les pointeurs copiés dans "tab" soient toujours valides même après avoir quitté la fonction.
    Puis, j'ai été pris d'un doute. En effet, ce n'est pas "orig" qui importe, mais son contenu. Et ce contenu, lui, provient de la zone (je ne me souviens plus son nom) qui contient les strings écrites en dur, exactement comme quand on écrit char *nom="toto". Bref, ayant sauvegardé les adresses de ces 3 strings dans "tab", adresses qui, elles restent inaliénable, que "orig" reste ou disparaisse importe peu.

    Voilà l'objet de mon questionnement. Le tableau "orig" nécessite-t-il de rester en static ou pas ? Accessoirement sans "static" ça compile et ça fonctionne aussi.

    Merci à tous.
    Hello,
    orig va contenir les adresses des chaînes qui comme ce sont des littéraux sont stockées dans une zone mémoire hors pile et hors tas qui est en lecture seule (en général). Donc static ou pas cela fonctionnera, avec la différence que static le tableau n'est initialisé qu'une seule fois au chargement du programme (et sera dans la même zone que les chaînes) ; sans static il sera initialisé à chaque appel sur la pile.
    Ça aurait été une autre paire de manches si tu avais produit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    void remplir(char *tab[]) {
    	static char orig[3][5]={"toto", "titi", "tata"};
    	for (int i=0; i < 3; i++) tab[i]=orig[i];
    }
    Là des copies des chaines sont faites … sur la pile sans static ça coince, dans un segment data ro avec le static et là ça passe.

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 711
    Points : 31 028
    Points
    31 028
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par WhiteCrow Voir le message
    Ça aurait été une autre paire de manches si tu avais produit...
    Ho super cet exemple !!!

    Merci de ton retour
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Membre éclairé
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Septembre 2015
    Messages
    204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de système d'information

    Informations forums :
    Inscription : Septembre 2015
    Messages : 204
    Points : 839
    Points
    839
    Par défaut
    Citation Envoyé par WhiteCrow Voir le message
    Donc static ou pas cela fonctionnera, avec la différence que static le tableau n'est initialisé qu'une seule fois au chargement du programme (et sera dans la même zone que les chaînes) ; sans static il sera initialisé à chaque appel sur la pile.
    Je viens de regarder le code assembleur généré et ça confirme

    avec static, il crée une structure contenant les chaines et dans le code, il copie la structure sur le nouvel objet
    sans static, il crée une chaine par élément du tableau orig (chaine1="toto", chaine2="titi", ...) et dans le code, il copie chaque élément dans la pile puis copie ensuite la pile dans le nouvel objet

    Avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    	static char orig[3][5]={"toto", "titi", "tata"};
    }
    Le code asm généré est quasiment le même qu'avec static, il ajoute seulement un positionnement dans le nouvel objet

  7. #7
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 677
    Points
    13 677
    Billets dans le blog
    1
    Par défaut
    Je suis en phase avec WhiteCrow.

    Pour moi, static ne sert à rien ici. Tu crées un tableau de pointeurs et tu le remplis avec l'adresse des 3 string literals. Tu copies ces adresses et tu quittes la fonction. A ce moment, on se fiche pas mal de ton tableau. Ce sont les adresses qui sont importantes : sont-elles encore valides ? La réponse est oui car les string literals existent pendant toute la durée de l'exécution du programme et leurs adresses ne changent pas.

    Je sais pas si ce comportement est garanti par la norme et j'ai la flemme de chercher pour le moment. En tout cas, c'était le cas avec toutes les toolchains que j'ai utilisé.

  8. #8
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 711
    Points : 31 028
    Points
    31 028
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Pour moi, static ne sert à rien ici. Tu crées un tableau de pointeurs et tu le remplis avec l'adresse des 3 string literals. Tu copies ces adresses et tu quittes la fonction. Ce sont les adresses qui sont importantes : sont-elles encore valides ? La réponse est oui car les string literals existent pendant toute la durée de l'exécution du programme et leurs adresses ne changent pas.
    C'était aussi l'idée que j'avais eu qui m'a amené à poser la question.
    Accessoirement, puisque tu as donné le terme, je me suis demandé si ça restait le cas avec autre choses que des string literals. J'ai donc remplacé l'exemple initial par celui-ci
    Code c : 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>
     
    typedef struct {
    	int x;
    } t_int;
     
    void remplir(t_int *tab[]) {
    	static t_int orig[]={{123}, {234}, {345}};
    	for (int i=0; i < 3; i++) tab[i]=&orig[i];
    }
     
    int main() {
    	t_int *tab[3];
    	remplir(tab);
    	for (int i=0; i < 3; i++) printf("tab[%d]=%d\n", i, tab[i]->x);
    }
    Et là, sans static, et en compilant avec l'option -O2, le truc part totalement à l'ouest (mais ça reste nickel sur le premier exemple à base de strings). Donc si pour un truc autre que des string literals le static est nécessaire, par homogénéité je serais amené à dire qu'il doit l'être tout le temps.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 677
    Points
    13 677
    Billets dans le blog
    1
    Par défaut
    C'est parce que ton code ressemble au 2e code de WhiteCrow.

    Tu utilises ici les literals eux-mêmes et non leurs adresses.

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 03/08/2009, 17h27
  2. Comment faire pour qu'un calque soit static, qu'il ne bouge pas
    Par beegees dans le forum Mise en page CSS
    Réponses: 10
    Dernier message: 27/08/2007, 11h34
  3. Réponses: 25
    Dernier message: 23/01/2007, 22h27
  4. enum imbriqués : static ou pas?
    Par ®om dans le forum Langage
    Réponses: 2
    Dernier message: 10/12/2006, 19h28
  5. section critique "static" ou pas?
    Par giova_fr dans le forum Windows
    Réponses: 2
    Dernier message: 01/01/2006, 13h15

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