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 :

Initialiser et afficher un tableau avec 2 fonctions sans paramètres


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Femme Profil pro
    Enseignant
    Inscrit en
    Novembre 2024
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 43
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Novembre 2024
    Messages : 3
    Par défaut Initialiser et afficher un tableau avec 2 fonctions sans paramètres
    Bonjour à tous, je suis débutant en programmation en C et j'ai une question sur le programme ci-dessous.

    Résumé sur le programme :
    • composé de deux fonctions, la 1ere void initialise_Nb_jours() initialise un tableau avec le nombre de jours du mois { 31 28 31 30 31 30 31 31} .
    • la 2eme fonction void affiche() affiche le tableau initialisé par la fonction précédente.
    • les deux fonctions sont sans paramètres d'entrées et sans paramètres de sorties. Au début de la fonction main, j'ai appelé la fonction initialise_Nb_jours(), ensuite la fonction affiche().


    Ma question : malgré le fait que les deux fonctions n'aient aucun paramètre d'entrée ni aucun paramètre de sortie, qu'elles ne retournent aucune valeur et malgré le fait que le tableau Nb_jours[13] soit un pointeur propre à la fonction initialise_Nb_jours(), le tableau affiche_Nb_jours[] (déclaré dans la 2eme fonction affiche() ) arrive à pointer sur les valeurs du tableau Nb_jours[13] afin de les afficher.

    SVP, pouvez vous m'expliquer cela ?

    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
    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
    58
    59
    #include <stdio.h>
     
    /* Fonction qui initialise le tableau Nb_jours */
    /* Paramètre d'entrée : aucun                  */
    /* Paramètre de sortie : rien                  */
     
    void initialise_Nb_jours()
    { int Nb_jours[13];
     
      /* Déclaration d'un compteur de mois */
      int RangMoins;
     
      /* Pour tous les mois de l'année */
      for(RangMoins = 1; RangMoins <= 12 ; RangMoins++)
      { /* Si mois est février */
        if(RangMoins == 2)
     
          /* Alors le nombre de jours est 28 */
          Nb_jours[RangMoins] = 28;
     
          /* Sinon, si le rand du mois est pair et <=7 ou impair et >7 */
          /* Alors le nombre de jours est 30                           */
          else if((RangMoins % 2 == 0 && RangMoins<=7) || (RangMoins % 2 != 0) && RangMoins>7)
          Nb_jours[RangMoins] = 30;
     
          /* Sinon le nombre de jours est 31 */
          else Nb_jours[RangMoins] = 31;
      } 
    }
     
    /* Fonction qui affiche le tableau Nb_jours */
    /* Paramètre d'entrée : aucun               */
    /* Paramètre de sortie : rien               */
     
    void affiche()
    { int affiche_Nb_jours[13];
     
      /* Déclaration d'un compteur de mois */
      int RangMoins;
     
      /* Pour tous les mois de l'année */
      /* Afficher le nombre de jours pour le mois en cours */
     
      for(RangMoins = 1; RangMoins <= 12 ; RangMoins++)
      printf("Le mois numero %d  de l'annee a %d jours\n", RangMoins, affiche_Nb_jours[RangMoins]);
    } 
     
    /****************************************************************************************/
    /*                               Programme principal                                                                                               */
    /****************************************************************************************/
     
    void main(void) 
    {
     /* Initialisation de Nb_jous */
     initialise_Nb_jours();
     
     /* Affichage de contenu du tableau */
     affiche(); 
    }

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

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

    Informations forums :
    Inscription : Septembre 2015
    Messages : 213
    Par défaut
    bonjour

    déjà utilise la balise "CODE" pour la lisibilité de ton code

    ton code fonctionne, car le compilateur a utilisé les mêmes zones de mémoire pour tes 2 fonctions
    lors de la compilation de la 2ème fonction, il savait qu'il pouvait réutiliser la zone mémoire de la 1ère fonction (car interne à la 1ère fonction)


    si par exemple, tu rajoutes entre initialise_Nb_jours(); et affiche(); un appel à une nouvelle fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void ma_fonction ()
    {
        int tab[7];            /* je prends volontairement une valeur plus petite pour que tu vois qu'il va peut-être écraser une partie de la mémoire) */
        for (int i=0;i<7;i++)tab[i]=2;
    }
     
    ...
    {
        initialise_Nb_jours();
        ma_fonction ();   /* appel à la nouvelle fonction */
        /* Affichage de contenu du tableau */
        affiche();
    }
    mais tu restes sur un comportement indéfini (tout dépend de comment le compilateur gère sa mémoire)

  3. #3
    Futur Membre du Club
    Femme Profil pro
    Enseignant
    Inscrit en
    Novembre 2024
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 43
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Novembre 2024
    Messages : 3
    Par défaut
    Merci beaucoup pour ta réponse détaillée.

  4. #4
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 771
    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 771
    Par défaut
    Je ne comprends
    • ni le but de l'exercice: travailler avec les variables globales. mais pourquoi ?
    • ni l'utilité de l'exercice: utiliser les variables globales. Sauf cas spécifiques (l'embarqué par exemple), les variables globales sont à éviter
    • ni ce qu'il faut faire: afficher juste 30 et 31 pour le mois 1 à 12 c'est moche


    1 solution
    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
    28
    29
    30
    31
    32
    #include <stdio.h>
    #include <stdlib.h>
     
     
    char list_nb_days[12];
     
    void init_nb_days() {
        list_nb_days[0] = list_nb_days[2] = list_nb_days[4] = list_nb_days[ 6] =
                          list_nb_days[7] = list_nb_days[9] = list_nb_days[11] = 31;
     
        list_nb_days[3] = list_nb_days[5] = list_nb_days[8] = list_nb_days[10] = 30;
     
        list_nb_days[1] = 28;
    }
     
    void display_nb_days() {
        char day;
     
        for(day=0; day < 12; ++day) {
            printf("month %2d, number of days: %d\n", (day + 1), list_nb_days[day]);
        }
    }
     
     
    int main()
    {
        init_nb_days();
        display_nb_days();
     
     
        return EXIT_SUCCESS;
    }

  5. #5
    Futur Membre du Club
    Femme Profil pro
    Enseignant
    Inscrit en
    Novembre 2024
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 43
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Novembre 2024
    Messages : 3
    Par défaut :|:|:|:|:|:|
    Je suis débutant et j'ai rien compris dans tous ce que tu as dit.

    Pour résumer, je m'entraine à programmer en C pour évoluer. C'est un programme que j'ai retrouvé dans un livre, le tableau est déclaré en global.
    J'ai effectué une petite modification, j'ai supprimé le tableau déclaré en globale et je l'ai remplacé par deux tableaux en local pour chaque fonction et le résultat était le même.
    J'avais un doute que le compilateur utilise la même zone mémoire pour les deux tableaux, du coup j'ai posé la question ici et j'ai eu la confirmation de Xelland.

  6. #6
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    Février 2008
    Messages
    2 315
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : Février 2008
    Messages : 2 315
    Billets dans le blog
    5
    Par défaut
    Bonjour.

    Pour essayer de faire le plus simple possible (je vais tenter de vulgariser au maximum ) en C (et en C++ aussi) ce qu'il faut avoir en tête c'est la division de la mémoire en deux parties distinctes:
    • la mémoire dans la pile ;
    • la mémoire dans le tas.


    La pile

    Tout d'abord sa taille. Elle est définie par ton système d'exploitation. En général 1Mo. Mais bien entendu elle peut être différente. Il est aussi possible de la modifier. En règle générale personne n'y touche.

    À quel moment je sais que j'utilise cette mémoire ?
    C'est tout simple. Un bloc mémoire est alloué à chaque fois que tu ouvres une accolade . Chaque fonction est définie par une paire d'accolades. À l'intérieur je peux donc déclarer des variables sans dépasser la taille allouée. Tu peux faire un essai en déclarant par exemple un tableau de int d'une taille de 10Mo. Regarde le résultat en console .

    Quelle est la durée de vie des variables déclarées dans une parie d'accolades ?
    La réponse est dans la question. Tant que ton code reste dans les accolades les variables déclarées à l'intérieur perdurent. Ainsi si tu appelles une fonction à l’intérieur d'une paire d'accolades et que tu y transmets ces variables, elles seront toujours viables dans la fonction appelée.

    Le tas

    Le tas correspond au reste de la mémoire de la machine sur laquelle tourne ton application. Pour y accéder nous faisons une allocation dynamique. C'est à dire nous utilisons la fonction malloc() (et ses dérivées). Cette méthode permet de dépasser la limitation que nous impose la taille de la pile.
    Et c'est là que nous allons entrer dans les problèmes . Qui dit allocation dynamique dit libération des blocs devenus inutiles. Ceci se fait avec la fonction free(). Bon nombre de programmeurs oublient de libérer certains blocs ce qui peut entrainer le crash de l'application et aussi permettre certains exploits pour pénétrer dans les systèmes. Mais ça c'est une autre histoire.


    En résumé avoir des variables globales, c'est à dire accessibles en tout point du programme est à fortement éviter. Le code devient rapidement difficile à maintenir voir à déboguer. L'art du C (et du C++) est en grande partie contenu ici. Arriver à faire en sorte de ne pas en avoir. Pour y parvenir il te faut maitriser les deux notions décrites ici. J'espère avoir pu apporter une petite pierre à ta compréhension.

  7. #7
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 409
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 409
    Par défaut
    Si ça fonctionne c'est parce que le compilateur aura pris la liberté de compiler les deux fonctions en "inline", c'est à dire aura placé leur contenu dans la fonction principale.
    Ce qui évite en arrière plan, au bas niveau, les CALL et RET... C'est de l'optimisation de code !!!

    Par contre, il faut respecter tout ce qui a été dit sur les déclarations globales, locales et la PILE (qui est ici un dispositif de bas niveau... niveau CPU) !

Discussions similaires

  1. Réponses: 0
    Dernier message: 10/05/2012, 08h33
  2. afficher des images avec une fonction
    Par wilfried_42 dans le forum Contribuez
    Réponses: 0
    Dernier message: 16/09/2008, 20h03
  3. Réponses: 4
    Dernier message: 17/07/2008, 12h24
  4. Réponses: 2
    Dernier message: 07/06/2007, 16h07
  5. cacher et afficher un tableau avec un "radio button"
    Par chrix10.2 dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 10/01/2007, 20h01

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