Annonce

Réduire
Aucune annonce.

Les allocations dynamiques en C

Réduire
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • Tutoriel Les allocations dynamiques en C

    bonjour à tous,

    Code:
    int main(int argc, char *argv[])
    {
        int nombreDAmis = 0, i = 0;
        int* ageAmis = NULL; // Ce pointeur va servir de tableau après l'appel du malloc
     
        // On demande le nombre d'amis à l'utilisateur
        printf("Combien d'amis avez-vous ? ");
        scanf("%d", &nombreDAmis);
     
        if (nombreDAmis > 0) // Il faut qu'il ait au moins un ami (je le plains un peu sinon :p)
        {
            ageAmis = malloc(nombreDAmis * sizeof(int)); // On alloue de la mémoire pour le tableau
            if (ageAmis == NULL) // On vérifie si l'allocation a marché ou pas
            {
                exit(0); // On arrête tout
            }
     
            // On demande l'âge des amis un à un
            for (i = 0 ; i < nombreDAmis ; i++)
            {
                printf("Quel age a l'ami numero %d ? ", i + 1);
                scanf("%d", &ageAmis[i]);
            }
     
            // On affiche les âges stockés un à un
            printf("\n\nVos amis ont les ages suivants :\n");
            for (i = 0 ; i < nombreDAmis ; i++)
            {
                printf("%d ans\n", ageAmis[i]);
            }
     
            // On libère la mémoire allouée avec malloc, on n'en a plus besoin
            free(ageAmis);
        }
     
        return 0;
    }
    Une petite question à propos de la fonction malloc, elle "transforme" notre pointeur en une variable (Ici un un tableau d'int) où la taille

    en octet(s) aura été renseigné littéralement ou grâce à la fonction "sizeof" ?

    EDIT : Voici un code qui me paraît plus logique :

    Code:
    int main(int argc, char *argv[])
    {
        int* memoireAllouee = NULL;
     
        memoireAllouee = malloc(sizeof(int)); // Allocation de la mémoire
        if (memoireAllouee == NULL)
        {
            exit(0);
        }
     
        // Utilisation de la mémoire
        printf("Quel age avez-vous ? ");
        scanf("%d", memoireAllouee);
        printf("Vous avez %d ans\n", *memoireAllouee);  
     
        free(memoireAllouee); // Libération de mémoire
     
        return 0;
    }
    La fonctin scanf demande une adresse en paramètre, "memoireAllouee" est donc bien un pointeur

    On pointe vers l'adresse écrite dans "memoireAllouee" grâce à -> memoireAllouee = malloc(sizeof(int)); <-

    on a bien créer une variable en mémoire avec l'allocation dynamique, sont adresse étant stocké dans

    le pointeur mémoireAllouee, le seul soucis c'est qu'on travaille avec des adresses et non plus avec

    des noms de variables ?
    Dernière modification par shirocen, 02 janvier 2015, 15h05.
    deux et deux font cinq

  • #2
    Je ne comprend pas où tu veux en venir avec ton 1er code, désolé, je ne vois pas grand chose de cohérent, avec un mélange de valeur et adresse.

    Une petite question à propos de la fonction malloc, elle "transforme" notre pointeur en une variable (Ici un int) où la taille

    en octet(s) aura été renseigné littéralement ou grâce à la fonction "sizeof" ?
    Alors il n'y nullement besoin de sizeof pour spécifier la taille du bloc d'adresses...

    Ensuite malloc crée un bloc d'adresse de type void dont la taille de type size_t est spécifiée.

    Le 2ème code est correct, enfin logiquement il le devrait, j'ai pas testé...

    Donc oui tu travailles avec des adresses, comme scanf demande une adresse, rien ne me choque sur cette façon de faire.

    Mais en fait entre ton 1er et 2ème code, je ne vois pas où tu veux en venir, si ce n'est que le 2ème est correct, le 1er fait un peu n'importe quoi, sachant que tu écrases à chaque fois la variable memoireAllouee.

    Commentaire


    • #3
      @Fred'

      Up' ! Je me suis trompé de code source ^_^.

      Je comprends pas le fait qu'on utilise "&ageAmis[i]" pour accéder au tableau et non pas

      "ageAmis[i]", puisque "ageAmis" est un pointeur il contient donc une adresse.

      De plus, on utilise aussi "ageAmis[i]" pour lire les valeurs du tableau, pourquoi ne pas

      utilisé " *ageAmis[i] " ???
      Dernière modification par shirocen, 02 janvier 2015, 15h22.
      deux et deux font cinq

      Commentaire


      • #4
        Ok, c'est plus cohérent comme code, mais je ne vois pas quoi te répondre de plus... ?

        EDIT: Pour répondre à

        Je comprends pas le fait qu'on utilise "&ageAmis[i]" pour accéder au tableau et non pas

        "ageAmis[i]", puisque "ageAmis" est un pointeur il contient donc une adresse.
        ageAmis contient un bloc d'entier (type int) et non int *

        Quand on fait ageAmis[i], nous avons donc une valeur et pas une adresse. Pour avoir une adresse il nous faudra ajouter l'esperluette &.
        Dernière modification par fred, 02 janvier 2015, 15h38.

        Commentaire


        • #5
          Mais tu es d'accord que dans le deuxième code, on utilise "memoireAllouee" pour désigner l'adresse

          et " *memoireAllouee" pour désigner sa valeur, j'arrive pas a faire le lien avec les tableaux..
          deux et deux font cinq

          Commentaire


          • #6
            Mais tu es d'accord que dans le deuxième code, on utilise "memoireAllouee" pour désigner l'adresse
            Qu'il en soit ainsi, faisons le sur ton 1er code...

            Il suffit de tester,

            Code:
            scanf("%d", ageAmis+i);
            au lieu de

            Code:
            scanf("%d", &ageAmis[i]);
            On voit bien qu'on joue avec les adresses

            Commentaire


            • #7
              Merci encore une fois fred' de m'avoir éclairé :

              -> &ageAmis[i] <=> &(ageAmis[i]) <=> ageAmis + i

              -> ageAmis[i] <=> *(ageAmis + i)

              EDIT : D'ailleurs en testant des trucs j'ai fais une drôle de découverte

              Code:
              #include <stdio.h>
              #include <stdlib.h>
              
              int main(int argc, char *argv[])
              {
                  int* memoireAllouee = NULL;
              
                  memoireAllouee = malloc(sizeof(int)); // Allocation de la mémoire
                  if (memoireAllouee == NULL)
                  {
                      exit(0);
                  }
              
                  // Utilisation de la mémoire
                  printf("Quel age avez-vous ? ");
                  scanf("%d", &memoireAllouee[0]);
                  printf("Vous avez %d ans\n", memoireAllouee[0]);
              
                  free(memoireAllouee); // Libération de mémoire
              
                  return 0;
              }
              Tout est tableau en fait x)
              Dernière modification par shirocen, 02 janvier 2015, 17h47.
              deux et deux font cinq

              Commentaire


              • #8
                Je pensais que ageAmis[i] était une variable, mais non en faite c'est juste une valeur ^_^ la notation "ageAmis[i]"

                désigne la valeur situé à l'adresse "ageAmis + i"

                Je suis bon ? :v
                deux et deux font cinq

                Commentaire


                • #9
                  Je crois que c'est encore flou pour toi concernant valeur, variable et adresse.

                  Une variable peut contenir aussi bien une adresse mémoire, qu'une valeur, il suffit de spécifier ce qu'on souhaite

                  Code:
                  int *v = /* la variable nommée v attend une adresse mémoire d'une variable de type int */
                  int v /* la variable nommée v attend une valeur de type int */
                  Je pense que tu devrais un peu mettre ton livre de côté, mes cours sont adaptés au vrai débutant en programmation + langage C, afin d'avoir les bonnes bases pour lire ce genre de livre par la suite.

                  Dans ton cas ça commence pour les variables au cours n°1 . Il est très important d'assimiler ce vocabulaire avant d'aller plus loin... et autant dire qu'on est déjà bien trop loin.

                  EDIT: Tout ce que tu découvres là, est déjà indiqué clairement dans tous mes cours.
                  Dernière modification par fred, 02 janvier 2015, 18h36.

                  Commentaire


                  • #10
                    Pour moi,

                    Une variable a :

                    - un nom
                    - une valeur
                    - une adresse

                    J'ai bien assimilé que la valeur d'une variable pouvait être une adresse (-> Les pointeurs).

                    Les tableaux sont une suites de variables de mêmes types.

                    tableau[0] = 1, tableau[2]...

                    Donc on peut dire qu'un tableau est-un ensemble de variable indépendante l'une de l'autre.

                    Arrivé au chapitre de l'allocation dynamique, j'ai bloqué sur aucun exemple,code, explications.

                    Le problème vient du fait de combiner allocation dynamique et tableau (Tiens, tout comme structures et pointeurs )

                    La fonction "malloc" nous permet de récupérer une adresse d'allocation dans la valeur d'un pointeur.

                    Comment je vois les choses :

                    === VARIABLE === | === ADRESSE === | === VALEUR ===

                    monPointeur | FFFFFF1 | FFFFF2
                    monPointeur[0]| FFFFFF2 | 0
                    monPointeur[1]| FFFFFF3 | 0

                    Ce schéma est-il correct ?

                    Pour moi chaque variable a son rôle, utilisé un pointeur en tant que tableau je comprends pas

                    ou alors comme tu dis dans ton post j'ai du zappé certaines bases.
                    Dernière modification par shirocen, 02 janvier 2015, 19h22.
                    deux et deux font cinq

                    Commentaire


                    • #11
                      Je ne comprend pas ton schéma, pour moi et pour tous d'ailleurs, un pointeur n'est pas équivalent à un tableau.

                      Voici un récapitulatif de ce qu'il faut comprendre

                      Code:
                      #include <stdio.h>
                      
                      int main(void)
                      {
                          int array[3] = {0, 1, 2};
                          int i;
                      
                          /* valeurs */
                          printf("%d\n", *array == array[0]);
                          printf("%d\n", *(array+1) == array[1]);
                          printf("%d\n", *(array+2) == array[2]);
                      
                      
                          /* adresses */
                          printf("%d\n", array == &(array[0]));
                          printf("%d\n", array+1 == &(array[1]));
                          printf("%d\n", array+2 == &(array[2]));
                      
                          /* pointeurs, on pointe sur une case mémoire, c'est une adresse */
                          int *p = array; /* déclaration d'un pointeur p */
                      
                          /* valeurs */
                          printf("%d\n", *p == array[0]);
                          printf("%d\n", *(p+1) == array[1]);
                          printf("%d\n", *(p+2) == array[2]);
                      
                          /* adresses */
                          printf("%d\n", p == &(array[0]));
                          printf("%d\n", p+1 == &(array[1]));
                          printf("%d\n", p+2 == &(array[2]));
                      
                          for (i=0; i<3; i++){
                          	printf("Valeur n°%d vaut %d\n", i, *p);
                          	p++;
                          }
                      
                          return 0;
                      }

                      Commentaire


                      • #12
                        Je dois dire Fred' qu'il me manque des notions au niveau des tableaus ou du langage C en général

                        pour la compréhension de ton code.

                        Je pensais que l'opérateur " * " s'utilisé UNIQUEMENT avec les pointeurs, le fait de le reprendre avec un tableau m'était inconnu ^_^

                        Donc on peut obtenir les valeurs du tableau en utilisant l'opérateur " * " (Tout comme on utilise " * " pour obtenir la valeur vers laquelle un pointeur pointe)

                        De plus, tu démontres que "array" correspond à une adresse, je n'avais jamais utilisé la variable "seul" d'un tableau

                        sans faire référence aux tableaux (array[0]..), je pense qu'il me manque vraiment des notions importantes pour continuer le cours

                        d'openclassroom, ou que les cours d'openclassroom vont à l'essentiel sans passé par détails que j'aurais aimé connaître.

                        Je vais recommencer mon apprentissage avec tes cours ! Dommage que sa soit la fin des vacances..

                        En fait, une variable n'est rien d'autre qu'une adresse et une valeur, c'est nous qui donnons un nom à l'adresse, et qui modifions

                        sa valeur par le biais de l'IDE.

                        Ton code m'a beaucoup éclairé, je vais le garder précieusement, c'est vraiment une mine d'info'.

                        Encore un grand merci Fred' pour ton aide !
                        Dernière modification par shirocen, 02 janvier 2015, 22h36.
                        deux et deux font cinq

                        Commentaire


                        • #13
                          Il y a une explication conceptuel pour les pointeurs que j'apprécie particulièrement. Toutes les valeurs que tu as à manipuler dans un programme passeront et seront temporairement stocké dans ta ram. Si tu compare la ram à un énorme building avec des appartements. Chaque octet est un étage. Tu souhaites déplacer un gros bloc d'étage (de octets). Plutôt que de déplacer ce bloque tu manipules juste son adresse. C'est bien plus rapide, et le postier (le pointeur) sera toujours ou trouver la valeur. Vu que les tailles des appartements son fixe. Tu peux bidouiller directement l'adresse pour retrouver les portions doctet supérieur et inférieur à ton adresse initial. C'est pourquoi sur un tableau. Tu peux incrémenter l'adresse mémoire. Cela est valable pour tout les types de variable. Finalement une fois la compilation faites tout est transformer en pointeur.
                          ToxID : 7322307290A75F5F36142EF206D95374966F10FE2CCD8224BEC07F16137875058C3BC4020609


                          Petite énigme, seriez vous décoder ce code ? WW4gZXJjYmFmciBoYXZpcmVmcnl5ciA/

                          Commentaire


                          • #14
                            L'objectif de mes cours était justement de réparer les erreurs pédagogiques d'openclassrooms, dans le sens où ils vont un peu vite pour un langage qui demande tellement de rigueur...

                            Commentaire


                            • #15
                              Superbe explication misterPoc; je vais tout recommencer de zéro avec les cours de fred' en espérant ne pas

                              avoir autant d'interrogations qu'avec le livre d'openclassroom.
                              deux et deux font cinq

                              Commentaire

                              Chargement...
                              X