Aller au menu - Aller au contenu

L'allocation dynamique


Pour accéder à cette section
Connectez-vous !
connexion_rpx
Page Précédente  1  2  3 
Pseudo Commentaire
Page Précédente  1  2  3 
Hors ligne tosca30 # Posté le 28/10/2009 à 16:14:39

Bonjour,

Je suis sous Linux/Ubuntu, et bloquée dans CodeBlocks dès le début de ce tuto : les instructions

Code : C
1
2
3
4
printf("char : %d octets\n", sizeof(char));
printf("int : %d octets\n", sizeof(int));
printf("long : %d octets\n", sizeof(long));
printf("double : %d octets\n", sizeof(double));


retournent ces erreurs lorque je lance la compilation :

Code : Autre
1
2
3
4
5
6
7
||=== projet_en_c, Debug ===|
/home/marie-noelle/projet_en_c/main.c||In function ‘main’:|
/home/marie-noelle/projet_en_c/main.c|9|attention : format ‘%d’ expects type ‘int’, but argument 2 has type ‘long unsigned int’|
/home/marie-noelle/projet_en_c/main.c|10|attention : format ‘%d’ expects type ‘int’, but argument 2 has type ‘long unsigned int’|
/home/marie-noelle/projet_en_c/main.c|11|attention : format ‘%d’ expects type ‘int’, but argument 2 has type ‘long unsigned int’|
/home/marie-noelle/projet_en_c/main.c|12|attention : format ‘%d’ expects type ‘int’, but argument 2 has type ‘long unsigned int’|
||=== Build finished: 4 errors, 0 warnings ===|


et je ne peux aller plus loin. J'ai tenté de recréer un projet, en spécifiant bien "C" comme langage, et le résultat est identique.

Merci pour votre aide.
Hors ligne Gabino1992 # Posté le 06/11/2009 à 23:35:54
Avatar

Salut !

Pourquoi ça marche quand on met :

printf ("%d ans",ageAmis[i]);

alors que ageAmis est un pointeur ??
je pensais qu'on devait mettre :

printf ("%d ans",*ageAmis[i]);

Expliquez moi svp

Quand on montre la lune du doigt, l'imbécile regarde le doigt.
 
Hors ligne Jerwan # Posté le 07/11/2009 à 17:09:38
Avatar

Ville : Montmeyran
Pays : France métropolitaine

Bonjour à tous;

c'est mon premier message :p

Est ce que quand on libère la mémoire (free); le pointeur est suprimé?

Merci d'avance;
Jerwan :D
Hors ligne Salokyn # Posté le 05/12/2009 à 15:45:58

Salut,

Super boulot que sont ces cours, vraiment bravo.

Sinon, je note une erreur dans la partie "La taille des variables".

Contrairement aux variables "int", les variables "long" ne font pas toujours 4 octets. Ici, c'est juste une coïncidence.

La taille d'un long correspond à la taille des registres du processeur. Sa taille est effectivement de 4 octets sur un processeur 32bits, mais elle est de 8 octets sur un processeur 64bits (et surement de 16 octets sur un processeur 128bit).

A+
Hors ligne Salokyn # Posté le 05/12/2009 à 16:38:52

Petite précision avant qu'on me dise "Oui, j'ai un proc 64bit mais mes long sont bien codés sur 4 octets".

Celà ne dépend pas juste du processeur, mais aussi de l'OS.
Si vous avez un processeur 64bit et un OS 32bit, vos long seront toujours codés sur 4 octets car le programme sera compilé pour fonctionner sur l'OS depuis lequel vous compilez (donc 32bits).

Il faut avoir un processeur 64bit ET un OS 64bit pour s'attendre à avoir ses long codés sur 8 octets.
Hors ligne LEnchanteur # Posté le 06/01/2010 à 20:28:10
T'es humain ou argent ?

Je ne comprends pas bien l'exercice juste avant le QCM et sur ce qu'on a vu sur les pointeurs . Regardez :
Code : C
1
2
3
4
5
6
7
8
for(i = 0; i < nombreAmis; i++)
        {
        printf("Quel est l'age de l'ami numero  %d : ", i+1);
        scanf("%d", &ageAmis[i]); // Ici on met un "&", alors que ageAmis est un pointeur
// En mettant un &, on modifie l'adresse comme on l'a vu dans les pointeurs, mais pourtant si j'enlève le & ça plante      
 printf("\n"); 

        }


Or dans le QCM à la quatrième question, il demande quelle est l'erreur dans le code suivant
Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
int main(int argc, char *argv[])
{
    int* pointeur = NULL;

    pointeur = malloc(sizeof(int));
    if (pointeur == NULL)
    {
        exit(0);
    }

    printf("Quel age avez-vous ? ");
    scanf("%d", &pointeur);
    printf("Vous avez %d ans\n", *pointeur);

    free(pointeur);
    

    return 0;
}


(J'ai fait une faute exprès)

Mauvaise réponse : Il y a une * en trop devant le pointeur dans la ligne du printf
La bonne réponse était : Il y a un & en trop devant le pointeur dans la ligne du scanf

Et voici l'explication

Explications : C'était une question du niveau du chapitre sur les pointeurs, j'espère que vous ne vous êtes pas plantés
En effet, il faut envoyer au scanf l'adresse à laquelle il peut écrire en mémoire. On doit donc lui indiquer l'adresse qui a été donnée par le malloc.
Cette adresse est stockée dans "pointeur" (tout court). Si vous indiquez &pointeur, vous indiquez l'adresse où se trouve le pointeur en mémoire, et non l'adresse qui a été réservée par le malloc pour stocker un int !

Alors ma question est ? Est-ce encore là un mystère inexplicable des pointeurs ? Ils sont juste là pour nous embêter ?

Citation : Declaire
Un monde gratuit moi j'y crois parce qu'on est humain et pas argent



 
Hors ligne 666by # Posté le 26/01/2010 à 19:18:48
Avatar

Enfait quand tu fait "&ageAmis[i]" c'est comme si tu fesait "*(ageAmis+i)" tu prend en realiter l'adresse d'une case d'un tableau et pas l'adresse du pointeur
j'espere t'avoir aidé
Hors ligne de courson # Posté le 30/01/2010 à 21:56:12

je tient juste à faire une remarque sur free et malloc

free ne libere pas la memoire

mais permet que malloc puis reutilise un espace dejas utilisé
Hors ligne hamzou90 # Posté le 03/02/2010 à 19:39:03

Ton tuto est geniale. Mais y'a un gros problème, au début t'as dis inspirer mais pas expirer :lol: (j'allais mourrir).
Non j'deconne :p
Hors ligne Adrien37 # Posté le 19/02/2010 à 01:17:12
A l'impossible nul n'est tenu.
Avatar

Ville : Tours
Pays : France métropolitaine

Salut à vous amis Zéros,

j'ai vu que plusieurs personnes avaient parlé des deux fonctions d'allocation de mémoire qui existent et qui n'apparaissent pas dans le cours : calloc() et realloc().
Je crois qu'il serait très utile de les expliquer. En effet, dans le TP du pendu par exemple, je me sers de ces deux fonctions qui permettent d'économiser pas mal de lignes de code.
Pour ceux qui l'ignorent :

1 . calloc() alloue de la mémoire comme malloc() mais fait quelque chose de plus : elle initialise toutes les cases mémoires à 0.
Voici son protype :Code : C
1
void *calloc(size_t num_elements, size_t size);

Ce qui fait que :
Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
char *maChaine = malloc(15 * sizeof(char));
int i;

if (maChaine == NULL) {
    printf("ERREUR : probleme de memoire.\n");
    system("PAUSE");
    exit(0);
}

for(i = 0; i < 15; i++)
    maChaine[i] = 0;
//suite du programme
est équivalent à :
Code : C
1
2
3
4
5
6
7
8
9
char *maChaine = calloc(15, sizeof(char));

if (maChaine == NULL) {
    printf("ERREUR : probleme de memoire !\n");
    system("PAUSE");//Pour qu'on ait le temps de lire le message.
    exit(0);
}

//suite du programme

C'est un peu plus concis non ?
Application : dans le TP du pendu, j'utilise calloc() pour allouer et initialiser la mémoire nécessaire au tableau de int de même longueur que le mot à trouver et dont les éléments passent à 1 lorsque l'utilisateur a trouvé une des lettres du mot.

2. realloc() s'utilise après qu'on ait utilisé la fonction malloc() ou calloc().
Voici son prototype : Code : C
1
void *realloc(void *ptr, size_t size);

realloc() modifie la taille de la zone mémoire précédemment attribuée à un pointeur par une des deux fonctions que j'ai citées et renvoie l'adresse de la nouvelle zone mémoire allouée.
Si la zone mémoire précédemment allouée peut être augmentée sans empiéter sur une zone mémoire utilisée pour autre chose, alors l'adresse mémoire renvoyée n'est pas modifiée (c'est la même que l'ancienne) mais le nombre de cases mémoires disponibles est modifié (c'était le but recherché).
En revanche, si en augmentant la zone mémoire initiale on déborde sur une zone mémoire déjà occupée, le système d'exploitation cherchera une autre adresse pour laquelle le nombre de cases mémoire nécessaires (fourni en argument de la fonction) est disponible.
exemple :
Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
char *maChaine = calloc(15, sizeof(char));
if (maChaine == NULL) {
    printf("ERREUR : probleme de memoire !\n");
    system("PAUSE");//Pour qu'on ait le temps de lire le message.
    exit(0);
}
//quelques instructions
maChaine = realloc(maChaine, 20 * sizeof(char))
if (maChaine == NULL) {
    printf("ERREUR : probleme de memoire !\n");
    system("PAUSE");
    exit(0);
}

L'instruction de la ligne 8 demande à ce que le pointeur maChaine puisse pointer sur 20 éléments de type char et attribue à maChaine l'adresse pour laquelle il y a 20 cases d'affilée disponibles pouvant contenir un char.

Problème : s'il faut changer d'adresse parce que l'ancienne pouvait contenir 15 char mais pas 20, les 20 octets (20 * sizeof(char) = 20 * 1 = 20 octets) disponibles seront ailleurs dans la mémoire. On peut se dire que la fonction realloc() a bien réservé 20 octets mais qu'elle n'a pas recopié les 15 char qui se trouvaient dans la zone mémoire précédemment allouée car la doc ne précise pas ce détail. L'expérience m'a montré que la fonction realloc() ne se contente pas d'allouer le nombre de cases demandées, elle recopie également les informations en cas de changement d'adresse.
Résultat : les informations qui étaient contenues dans l'ancien espace mémoire sont recopiées et il n'y a pas besoin de faire une recopie des anciennes valeurs vers la nouvelle adresse mémoire. Pas besoin de se préoccuper de ce détail. Simple et efficace cette fonction, non ? :)

Ce qui fait que si on veut faire la même opération avec seulement les instructions malloc() et free(), c'est plus compliqué et cela donne :
Code : C
 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
char *maChaine = malloc(15 * sizeof(char)), *copieDeMaChaine = NULL;
//15 ou plus probablement la valeur d'une variable.
int i;

if (maChaine == NULL) {
    printf("ERREUR : probleme de memoire.\n");
    system("PAUSE");
    exit(0);
}
for (i = 0; i < 15; i++) //Il n'est pas toujours nécessaire d'initialiser les élements à 0.
    maChaine[i] = 0;

// quelques instructions 
copieDeMaChaine = malloc(15 * sizeof(char));
if (copieDeMaChaine == NULL) {
    printf("ERREUR : probleme de memoire.\n");
    system("PAUSE");
    exit(0);
}

for (i = 0; i < 15; i++)
    copieDeMaChaine[i] = maChaine[i]; //On enregistre les données pour ne pas les perdre.
 
free(maChaine);//On libére la zone mémoire avant d'en acquérir une nouvelle.
maChaine = malloc(20 * sizeof(char)); //On demande plus de place en mémoire.

if (maChaine == NULL) {
    printf("ERREUR : probleme de memoire.\n");
    system("PAUSE");
    exit(0);
}

for (i = 0; i < 15; i++)
    maChaine[i] = copieDeMaChaine[i]; //On récupère les valeurs qu'on a sauvegardées.
free(copieDeMaChaine);//On peut maintenant supprimer les données sauvegardées.
 
//quelques instructions
free(maChaine); //On n'oublie pas de libérer la mémoire à la fin du programme ou de la fonction.

Et tout ceci est équivalent à :
Code : C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
char *maChaine = calloc(15, sizeof(char));
if (maChaine == NULL) {
    printf("ERREUR : probleme de memoire.\n");
    system("PAUSE");
    exit(0);
}

//quelques instructions
maChaine = realloc(maChaine, 20 * sizeof(char));
if (maChaine == NULL) {
    printf("ERREUR : probleme de memoire.\n");
    system("PAUSE");
    exit(0);
}

//quelques instructions
free(maChaine); //On n'oublie pas de libérer la mémoire.

J'ai parlé de concision pour calloc() tout à l'heure. Là, on est servi ! :)

Dans ces exemples, on pourrait remplacer la boucle for() par la fonction strcpy(). Cela est vrai parce qu'on utilise des char mais on ne peut plus utiliser cette fonction dès lors qu'on manipule autre chose que des char, comme des int, des double etc. Donc l'utilisation de la boucle for() est une technique qui marchera dans tous les cas de figure.

Application : dans le TP du pendu, je veux mémoriser chaque nouvelle lettre que l'utilisateur propose. Il faut donc allouer dynamiquement de la mémoire. Sauf qu'au premier coup, aucune case mémoire n'est encore allouée. Je fais donc appel à malloc(). Par la suite, je veux augmenter d'une case cette zone mémoire pour y stocker la nouvelle lettre. Je fais donc appel à realloc().
Ce qui donne :
Code : C
1
2
3
4
lettresProposees = nombreLettresProposees == 0 ? malloc(sizeof(char)) : realloc(lettresProposees, (nombreLettresProposees+1) * sizeof(char));
if (lettresProposees == NULL) memoire_saturee(); //La fonction memoire_saturee() affiche un message d'erreur et termine le programme.
lettresProposees[nombreLettresProposees] = lettre;
nombreLettresProposees++;


lettresProposees est un pointeur de char qui stocke les lettres proposées et nombreLettresProposees est une variable de type int qui, comme son nom l'indique, compte le nombre de lettres (différentes) que l'utilisateur a proposées. (Ils sont bien mes noms hein ? :D )

Autre chose : ici je fais d'une pierre deux coups en utilisant l'opérateur ternaire (x ? y : z;), opérateur à ne pas négliger car il se révèle être d'une grande utilité. Je m'en sers fréquemment personnellement.

Voilà, c'était un peu long mais j'ai abordé plusieurs sujets. J'espère que c'était clair pour tous.

A plus les Zéros ! ;)

Image utilisateurImage utilisateur
 
Hors ligne jja # Posté le 26/02/2010 à 12:26:40
Avatar

bonjour à tous
je tente de saisir le prenom des amis avec leur age, tout fonctionne sauf que à l'affichage :


combien d'ami(e) a tu ? 3

comment se nomme l'ami 1 : antoine

quel age de antoine ? 3

comment se nomme l'ami 2 : celine

quel age de celine ? 4

comment se nomme l'ami 3 : jerome

quel age de jerome ? 5

acjerome est age de 3 ans

cjerome est age de 4 ans

jerome est age de 5 ans


Process returned 0 (0x0) execution time : 36.
Press any key to continue.

je ne comprend pas pourquoi, çà viens de quoi ?
si quelqu'un peu m'expliquer ce serait genial


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void viderBuffer();

int main()
{
int n_ami =0 , i=0;
char *prenom = {0};

int*ageAmi = NULL;

printf("combien d'ami(e) a tu ? ");
scanf("%d",&n_ami);

if(n_ami>0)
{
ageAmi=malloc(n_ami * sizeof(int));
if (ageAmi ==NULL)
{exit(0);
}

prenom=malloc(n_ami * sizeof(char[25])); // crée un tableau pour les prenoms
if(prenom==NULL)
{ exit(0); }

// on demande l'age des amis
for(i=0;i<n_ami;i++)
{
printf("\n comment se nomme l'ami %ld : ",i+1);
scanf("%s",&prenom[i]);


printf("\n quel age de %s ? ",&prenom[i]);
scanf("%d",&ageAmi[i]);
}

for(i=0;i<n_ami;i++)
{
printf("\n %s est age de %d ans \n",&prenom[i],ageAmi[i]);
}
free(ageAmi);
free(prenom);
}

return 0;
Hors ligne Adrien37 # Posté le 07/03/2010 à 08:58:22
A l'impossible nul n'est tenu.
Avatar

Ville : Tours
Pays : France métropolitaine

Ceci est, comme son nom l'indique, un espace pour les COMMENTAIRES, pas pour les questions.
Posez vos questions sur le forum, il est là pour ça.

Image utilisateurImage utilisateur
 
Hors ligne Masado # Posté il y a 1h25
I'm a noob =)
Avatar

En relisant le tuto, je le trouve incomplet sur un point, aucun exemple quant au passage d'un pointeur par une fonction. C'est quand même l'utilisation première du pointeur ?! De même qu'il n'est pas expliqué comment faire une chaîne de caractère. Même si cela n'est pas très compliqué. C'est en général pour ces deux cas qu'on à souvent affaire aux malloc.

Mon jeu de management de golf en ligne
Je recherche un ou plusieurs designers ainsi que des testeurs pour un remake du jeu des echecs qui a pour vocation d'être un jeu online ici
Modèle complet de GameDesignDocument
Mon projet achevé : Alphator
Jeu réalisé en C++ a l'aide de la SDL. Version actuelle : 2.0
A télécharger ici !

Projet de MMORPG Azurion

Image utilisateur
 
Pour accéder à cette section
Connectez-vous !
connexion_rpx