Petit problème C

Moderator: Mod

Petit problème C

Postby MYRANOVA » Thu Jun 10, 2010 4:17 pm

j'essai de faire le 3 exercice du site du zero ici hxxp://www.siteduzero.com/tutoriel-3-14015-les-tableaux.html

mais ca marche pas, meme quand je met " copie(tableau,tableauCOP,7);" dans le printf ca m'affiche un mauvais résultat comme 229500.

Regardez le code :
[code:1:112833ad5d]
#include <stdio.h>
#include <stdlib.h>

long copie(long tableauOriginal[], long tableauCopie[], long tailleTableau);

int main()
{
long tableau[] = {2,5,7,8,0,76,988};
long tableauCOP[] = {0};

tableauCOP = copie(tableau,tableauCOP,7);

printf("%d", tableauCOP);
}

long copie(long tableauOriginal[], long tableauCopie[], long tailleTableau)
{
int i = 0;

for(i = 0 ; i < tailleTableau ; i++)
{
tableauCopie[i] = tableauOriginal[i];
}

return tableauCopie;
}
[/code:1:112833ad5d]
MYRANOVA
Projets
 
Posts: 28
Joined: Fri Apr 02, 2010 4:06 am

Postby TorTukiTu » Thu Jun 10, 2010 4:56 pm

[code:1:e914ca6f03]
long tableauCOP[] = {0};

printf("%d", tableauCOP); [/code:1:e914ca6f03]

tableauCOP est un pointeur. Ce n'est pas un décimal, d'où ta valeur apparemment étrange, c'est en réalité une adresse mémoire.

Voici une des solutions possibles:

[code:1:e914ca6f03]#include <stdlib.h>
#include <stdio.h>

int * copie(int * tableau1, int * tableau2, int tailleTableau);

int main(){
int i=0;
int * tableau;
int * tableau2;
tableau=(int*)calloc(3,sizeof(int));
tableau[0]=1;
tableau[1]=2;
tableau[2]=3;
tableau2=copie(tableau, tableau2, 3);
for(i=0; i<3; i++){
printf(" La case %d du tableau2 est egale a %d\n",i, tableau2[i]);
}
free(tableau);
free(tableau2);
return 1;
}

int * copie(int *tableau1, int *tableau2, int tailleTableau){
int i=0;
tableau2 = (int *)calloc(tailleTableau, sizeof(int));
for(i=0; i<tailleTableau; i++){
tableau2[i]=tableau1[i];
}
return tableau2;
}
[/code:1:e914ca6f03]

La tortue.
User avatar
TorTukiTu
Site Admin
 
Posts: 1960
Joined: Thu Feb 07, 2008 10:24 pm
Location: Devant son pc durant la redaction de ce message

Postby MYRANOVA » Thu Jun 10, 2010 5:48 pm

il faut que je vois les allocations dynamiques alors ?
MYRANOVA
Projets
 
Posts: 28
Joined: Fri Apr 02, 2010 4:06 am

Postby TorTukiTu » Thu Jun 10, 2010 8:38 pm

Non, pas forcément.

C'était un mauvais exemple d'utiliser une allocation dynamique pour des tableaux aussi petits.

La tortue.
User avatar
TorTukiTu
Site Admin
 
Posts: 1960
Joined: Thu Feb 07, 2008 10:24 pm
Location: Devant son pc durant la redaction de ce message

Postby ST4NL3Y » Tue Jul 26, 2011 10:41 am

Déjà faut que tu sache que lorsque tu envoi un tableau à une fonction comme ceci sans adresse, le compilateur va creer un tableau local au sein de la fonction et proceder a une simple copie, en gros tu perds de l'espace mémoire, soit du temps, et du rendement.

Normalement tu devrais faire :


[code:1:f2a89cacaa]

int main()
{
int Tableau[10];

mafonction(Tableau, 10);
return 0;
}


void mafonction(int *Tableau, int size)
{
int i;
for(i=0; i<size; i++) Tableau[i] = i; // Ici on insère les valeurs directement à l'adresse de tableau
}

[/code:1:f2a89cacaa]

Et sinon autre que les soucis de performances, ici si je reprends cette ligne :
[code:1:f2a89cacaa]printf("%d", tableauCOP); [/code:1:f2a89cacaa]

Et que je traduit celà veux dire :

Afficher un entier qui est => une adresse.

Je te laisse donc réfléchir dessus :)[/code]
Last edited by ST4NL3Y on Wed Jul 27, 2011 2:57 pm, edited 1 time in total.
ST4NL3Y
Projets
 
Posts: 10
Joined: Tue Jul 26, 2011 10:13 am

Postby Manu404 » Tue Jul 26, 2011 1:18 pm

Déterrage de topic vieux d'un an... a éviter :wink:
User avatar
Manu404
 
Posts: 2219
Joined: Tue Feb 26, 2008 3:44 pm
Location: ::1:

Postby THE-DEATH » Tue Jul 26, 2011 9:52 pm

erf oue, apres un an pas de reponse donc sert a rien d'apporter une solution. Eventuellement un probleme similaire pour pas creer un nouveau poste mais la tu reveilles les morts cest pas bien.
User avatar
THE-DEATH
 
Posts: 971
Joined: Wed Jul 23, 2008 10:49 am
Location: 127.0.0.1

Postby ST4NL3Y » Wed Jul 27, 2011 10:58 am

Ah oui désolé je n'avais pas vu la date exacte ...
Bah ça pourra servir pour les prochaines personnes au pire !
ST4NL3Y
Projets
 
Posts: 10
Joined: Tue Jul 26, 2011 10:13 am

Postby SPL3EN » Wed Jul 27, 2011 2:15 pm

Et en plus le code n'est pas totalement correct :/

1) void mafonction(int *Tableau, int size)
typeof(&Tableau) != int *, même un compilateur pas très évolué te notifiera ce warning.

2) creer un tableau local au sein de la fonction et proceder a une simple copie
Faux, c'est vrai pour les structures et les types natifs mais nullement pour le passage d'une référence. (il y a simplement copie de la référence et non du contenu de la référence, un tableau étant une référence sur le premier élément du tableau)

[spoiler:ab56cf6a94]La preuve : [code:1:ab56cf6a94]
#include <stdio.h>
#include <stdlib.h>

void function (char tableau[])
{
printf("%p\n", &tableau[0]);
tableau[0] = 'C';
}

int main()
{
char tableau[] = "Bonjour";
printf("%p\n", &tableau[0]);

function(tableau);

printf("%s\n", tableau);
}
[/code:1:ab56cf6a94]

Output :

[code:1:ab56cf6a94]
0022FF68
0022FF68
Conjour
[/code:1:ab56cf6a94]

Tandis que :
[code:1:ab56cf6a94]
#include <stdio.h>
#include <stdlib.h>

typedef struct _test
{
int a;
int b;

} Test;

void function (Test tableau)
{
printf("%p\n", &tableau.a);
tableau.a = 1337;
}

int main()
{
Test tableau = {1, 2};

printf("%p\n", &tableau.a);

function(tableau);

printf("%d\n", tableau.a);

}
[/code:1:ab56cf6a94]

Output :
[code:1:ab56cf6a94]
0022FF70
0022FF68
1
[/code:1:ab56cf6a94]

-> Les résultats parlent d'eux même
[/spoiler:ab56cf6a94]

Donc bref, voilà, au moins cette réponse bien tardive sera un tant soit peu utile pour quelqu'un.
User avatar
SPL3EN
Projets
 
Posts: 31
Joined: Mon Jun 21, 2010 5:21 pm

Postby ST4NL3Y » Wed Jul 27, 2011 2:56 pm

Sauf que si tu regarde son code c'est pas un le tableau du main qui est directement modifié, il utilise le principe de la copie :

[code:1:f69e52bec5]

int main()
{

int tableau[10];
int tableau2[10];

tableau = mafonction(tableau2);

return 0;

}

int* mafonction(int *tableau, int size)
{
int tableau_tmp[10];

/*


truc muche


*/

return tableau_tmp; // La copie se fait ici On a donc bien l'allocation du tableau temporaire + copie + liberation mémoire, et non pas une modification directe pour gagner en performance.
}[/code:1:f69e52bec5]

Edit : Et pour le passage en fonction de &tableau, ça faisait enormement de temps que je n'avais plus fais de C, m'étant uniquement consacré au C++ ces derniers mois j'en avais presque oublié pointeurs (presque).
ST4NL3Y
Projets
 
Posts: 10
Joined: Tue Jul 26, 2011 10:13 am

Postby SPL3EN » Wed Jul 27, 2011 4:39 pm

[quote:2faa6336e5]
return tableau_tmp; // La copie se fait ici On a donc bien l'allocation du tableau temporaire + copie + liberation mémoire, et non pas une modification directe pour gagner en performance.
[/quote:2faa6336e5]

Et bien non
Comme le dit lui même le prototype de la fonction :
[u:2faa6336e5]int* [/u:2faa6336e5]mafonction

On retourne [b:2faa6336e5]une référence [/b:2faa6336e5]sur le premier élément du tableau déclaré de manière [b:2faa6336e5]locale[/b:2faa6336e5].
Mais pas une copie. Seulement une copie de la référence.

[quote:2faa6336e5]
char* function ()
{
char tab[10];
printf("%p\n", &tab[0]);
return tab;
}

int main()
{
char *tab_main;
tab_main = function();
printf("%p\n", &tab_main[0]);
}
[/quote:2faa6336e5]

[quote:2faa6336e5]
>>
0022FF60
0022FF60
[/quote:2faa6336e5]

Deuxièmement,
[quote:2faa6336e5]si tu regarde son code c'est pas un le tableau du main qui est directement modifié[/quote:2faa6336e5]
Désolé mais c'est le contraire :

[quote:2faa6336e5]int main()
{
long tableau[] = {2,5,7,8,0,76,988};
long tableauCOP[] = {0};

tableauCOP = copie(tableau,tableauCOP,7);

printf("%d", tableauCOP);
}

long copie(long tableauOriginal[], long tableauCopie[], long tailleTableau)
{
int i = 0;

for(i = 0 ; i < tailleTableau ; i++)
{
tableauCopie[i] = tableauOriginal[i];
}
return tableauCopie;
}
[/quote:2faa6336e5]

Et dans ton dernier exemple, le retour d'une référence sur une variable déclarée localement est une erreur, mais décelée généralement par ton compilateur configuré par défaut.
C'est une erreur grave puisque cette référence est censée pointer vers une zone mémoire désallouée.

[quote:2faa6336e5]main.c|10|warning: function returns address of local variable|[/quote:2faa6336e5]
User avatar
SPL3EN
Projets
 
Posts: 31
Joined: Mon Jun 21, 2010 5:21 pm

Postby ST4NL3Y » Thu Jul 28, 2011 7:34 am

[code:1:63e8aadbbb]#include <stdio.h>
#include <stdlib.h>

int* mafonction();

int main()
{
int *tab;
int i;
tab = malloc(sizeof(int)*10);
printf("Adresse du tableau : %p\n", &tab);
tab = mafonction();
printf("Adresse après modification : %p\n", &tab);
for(i=0; i<10; i++) printf("%ld ", tab[i]);
return 0;
}


int* mafonction()
{
int *tab_tmp;
tab_tmp = malloc(sizeof(int) * 10);
int i;
for(i=0; i<10; i++) tab_tmp[i] = i;
printf("Adrese du tableau provisoire : %p\n", &tab_tmp);
return tab_tmp;
}
[/code:1:63e8aadbbb]


Renvoi d'adresse où pas, code preuve à l'appuie, tout les éléments du tableau provisoire son copier uns à uns vers le tableau du main, puis le tableau provisoire est désalloué regarde par toi même :




[code:1:63e8aadbbb]Adresse du tableau : 0022FF18
Adrese du tableau provisoire : 0022FEE8
Adresse aprÞs modification : 0022FF18
0 1 2 3 4 5 6 7 8 9[/code:1:63e8aadbbb]

Et pour ce qui est des petites erreurs de compilo, comme je te l'ai dis précédemment cela faisait énormément de temps que je n'avais pas programmé en C, mais comme tu le dis si bien avec un compilo c'est vite corrigeable.

Edit : par contre en relisant son code j'ai effectivement vu qu'il n'utilisait pas de tableau locale, je suis désolé donc, sinon le code en propre ça donne ça (au cas où) :

[code:1:63e8aadbbb]Valeurs du tableau copie :
0 1 2 3 4 5 6 7 8 9
Process returned 0 (0x0) execution time : 0.031 s


#include <stdio.h>
#include <stdlib.h>

void copie(int*,int*,int);
int main()
{
int *tab;
int *tab_copie;
int i;
tab_copie = malloc(sizeof(int)*10);
tab = malloc(sizeof(int)*10);
for(i=0; i<10; i++) tab[i] = i;
copie(tab, tab_copie, 10);
printf("Valeurs du tableau copie :\n");
for(i=0; i<10; i++) printf("%d ", tab_copie[i]);
return 0;
}

void copie(int *tab1, int *tab2, int size)
{
int i;
for(i=0; i<size; i++) tab2[i] = tab1[i];
}

[/code:1:63e8aadbbb][/code]
ST4NL3Y
Projets
 
Posts: 10
Joined: Tue Jul 26, 2011 10:13 am

Postby SPL3EN » Fri Jul 29, 2011 11:53 am

Hum...
Bon tout d'abord, le code que tu as donné est le correct.
Mais ce que je voulais dire depuis le début en fait, c'est qu'il existe déjà une fonction toute faite et bien plus optimisée pour ce genre d'opération : memcpy.
Ca a fait tout de même un bon exercice :)

Bref, sinon le premier code (censé me démontrer je ne ciomprends pas quoi) ne montre rien :

main : [code:1:397e67387a]tab = malloc(sizeof(int)*10);
[/code:1:397e67387a]
Ok, tu alloues 10*int de mémoire dont le pointeur est tab
Puis tu affiches [b:397e67387a]l'adresse du pointeur[/b:397e67387a][code:1:397e67387a]
printf("Adresse du tableau : %p\n", &tab);
>> Adresse du tableau : 0022FF18 [/code:1:397e67387a]
Très bien, certes.

main : [code:1:397e67387a]tab = mafonction();[/code:1:397e67387a]

Tu demandes à ce que l'adresse que pointait tab soit modifiée par le retour de la fonction mafonction. Ok.

mafonction :[code:1:397e67387a] tab_tmp = malloc(sizeof(int) * 10);
[...]
return tab_tmp;[/code:1:397e67387a]
Tu alloues 10 nouveaux int, tu attribues leur pointeur à tab_tmp que tu retournes.
tab dans le main (étant actuellement l'adresse de 10 int en mémoire) va donc prendre la valeur de l'adresse de 10 autres int quelque part d'autre dans la mémoire.

Par contre, là où il y a malaise, c'est qu'en pensant faire un return tab_tmp, tu penses "désallouer" le contenu d'un "tableau temporaire" contenu dans tab_tmp.
Ca marche pour les tableaux déclarés de façon locales, comme char tab_tmp[10], mais ça ne marche pas comme ça pour les pointeurs.

De ce fait, il y a une fuite mémoire dans ton programme :
L'adresse de la mémoire allouée par le premier tab = malloc(sizeof(int) * 10); dans le main est perdu par l'écrasement de cette adresse par celle retournée par mafonction.
Il est donc inutile d'allouer un quelconque espace mémoire pour tab puisque mafonction s'en charge.

Et là où intervient le second malaise, c'est quand tu check l'adresse du pointeur après l'appel de mafonction.
[code:1:397e67387a]printf("Adresse après modification : %p\n", &tab); [/code:1:397e67387a]
Bien évidemment elle n'aura pas changée puisque tu ne l'as pas modifiée. (tu as modifié tab lui même mais jamais son adresse)
Néanmoins, ce n'est pas de &tab dont tu devrais t'intéresser, mais de tab lui même.

Bref, je sens une large confusion avec tout ce qui est variable déclarée globalement/statistiquement, pointeurs et adresses, des notions bien moins importantes en orienté objet donc je comprends.

En tout cas problème résolu :)
User avatar
SPL3EN
Projets
 
Posts: 31
Joined: Mon Jun 21, 2010 5:21 pm

Postby ST4NL3Y » Fri Jul 29, 2011 12:37 pm

Effectivement j'ai oublié de free(), mais comme je te l'ai dis je programme plus en C donc j'ai perdu énormément de réflexes, de plus je me suis oreinté vers des tableaux dynamique car je ne me souvenais plus de la syntaxe exacte lors de tableau statique(qui eux serait désallouée lors du return).
Mais ce que je voulais te montrer c'est qu'il y a bien une copie de chaque éléments du tableau local vers le tableau du main, et non pas une copie adresse mémoire qui écraserait l'adresse du précédant tableau.
Mais je crois que depuis le débuts on est en Quiproquo.
ST4NL3Y
Projets
 
Posts: 10
Joined: Tue Jul 26, 2011 10:13 am

Postby SPL3EN » Sun Jul 31, 2011 1:43 am

[quote:3c512266ac]Mais ce que je voulais te montrer c'est qu'il y a bien une copie de chaque éléments du tableau local vers le tableau du main, et non pas une copie adresse mémoire qui écraserait l'adresse du précédant tableau.
Mais je crois que depuis le débuts on est en Quiproquo.[/quote:3c512266ac]
Je me tue à te montrer que c'est faux, et que ton exemple n'est pas un bon exemple puisqu'il est erroné... bon sang >.<

Enfin bref, j'ai eu cette discussion en pensant que ça puisse t'aider, mais le C n'a plus l'air de t'intéresser, alors ça n'est pas la peine que je fasse l'effort de réexpliquer :-)
User avatar
SPL3EN
Projets
 
Posts: 31
Joined: Mon Jun 21, 2010 5:21 pm


Return to C/C++

Who is online

Users browsing this forum: No registered users and 2 guests

cron