Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[Basique] Passage/modification de tableau dans une fonction

20 réponses
Avatar
Morgan Sangeux
Bonjour,
Malgres mes lectures et recherche sur le langage C je ne comprend pas le
fonctionnement du passage/modification d'un tableau dans une focntion.
Voici un exemple ci-après de ce que je voudrais faire et qui ne marche pas.

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

int test(double *);

int test(double * Coord, int taille)
{ int i;
Coord = (double *)realloc(Coord,taille * 3 * sizeof(double));
for(i=3;i<6;++i) {Coord[i]=2.0;printf("Coord[%d] =
%f\n",i+1,Coord[i]);}
return 0;
}

int main()
{
int taille, i,j, retour;
double * Coord;

taille =1;
Coord = (double *)malloc(3*sizeof(double));
for (i =0 ;i<3;++i) {Coord[i]=1.0;printf("Coord[%d] =
%f\n",i+1,Coord[i]);}
taille++;
retour = test(Coord,taille);
for(i = 3 ;i<6;++i) printf("Coord[%d] = %f\n",i+1,Coord[i]);
return 0;
}
"
la fonction modifie bien la taille de mon tableau Coord mais pas le
contenu,pourquoi?

10 réponses

1 2
Avatar
Pierre Maurette
[...]
En C, on ne passe à une fonction que des copies de valeurs. L'argument
de la fonction devient dans la fonction une variable locale. Quand vous
passez double * Coord, vous pouvez modifier le pointeur Coord comme le
fait realloc(), mais cette modification ne sortira pas de la fonction.
En revanche, si vous modifiez *Coord , ou *(Coord + N), cette
modification sera pérenne, observable depuis l'appelant après le
retour.

Il y a quelques erreurs dans votre code. Utilisez des constantes
nommées ou des macros plutôt que des numériques dans le code. Et je ne
vois pas trop ce que fait taille dans votre programme. Voici une base
de réflexion:

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

double* test(double*, int);

double* test(double* Coord, int taille)
{
int i;
double* RetCoord = realloc(Coord,taille * 3 * sizeof(double));
for(i=3;i<6;++i) {RetCoord[i]=2.0;printf("Fonction / Coord[%d] =
%fn",i+1,RetCoord[i]);}
return RetCoord;
}

int main()
{
int taille, i;
double* Coord = NULL;
taille =1;
Coord = malloc(3*sizeof(double));
for (i =0 ;i<3;++i) {Coord[i]=1.0;printf("Main 1 / Coord[%d] =
%fn",i+1,Coord[i]);}
taille++;
Coord = test(Coord,taille);
for(i = 3 ;i<6;++i) printf("Main 2 / Coord[%d] =
%fn",i+1,Coord[i]);
free(Coord);
return 0;
}

--
Pierre Maurette
Avatar
Morgan Sangeux
[...]
En C, on ne passe à une fonction que des copies de valeurs. L'argument
de la fonction devient dans la fonction une variable locale. Quand vous
passez double * Coord, vous pouvez modifier le pointeur Coord comme le
fait realloc(), mais cette modification ne sortira pas de la fonction.
En revanche, si vous modifiez *Coord , ou *(Coord + N), cette
modification sera pérenne, observable depuis l'appelant après le retour.

Merci pour votre réponse.

Je souhaite que ma fonction test me renvoi la taille du nouveau tableau,
normalement la taille est déterminée à l'interieur de la fonction (pas
dans le test mais 'en vrai' oui).
D'après ce que vous me dites si je fais ça:

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

int test(double*);

int test(double* Coord, int taille)
{ int i;

taille++;
Coord = (double *)realloc(Coord,taille * 3 * sizeof(double));
/* ligne d'interet ci-apres */
for(i=3;i<6;++i) {*(Coord+i)=2.0;printf("Coord[%d] =
%fn",i+1,Coord[i]);}

return 0;
}

int main()
{
int taille, i,j, retour;
double *Coord;

taille =1;
Coord = (double *)malloc(3*sizeof(double));
for (i =0 ;i<3;++i) {Coord[i]=1.0;printf("Coord[%d] =
%fn",i+1,Coord[i]);}
retour = test(Coord,taille);
for(i=3;i<6;++i) printf("Coord[%d] = %fn",i+1,Coord[i]);

free(Coord);
return 0;

}
ça devrait marcher mais ça marche pas. Je ne comprends pas car
normalement je modifie bien ce qui l'y a à 'l intérieur' de ma case
d'adresse Coord+i donc ça devrait etre connu a l'exterieur de la
fonction, non?
Il y a quelques erreurs dans votre code. Utilisez des constantes nommées
ou des macros plutôt que des numériques dans le code. Et je ne vois pas
trop ce que fait taille dans votre programme. Voici une base de réflexion:


Avatar
Pierre Maurette
[...]
En C, on ne passe à une fonction que des copies de valeurs. L'argument de
la fonction devient dans la fonction une variable locale. Quand vous passez
double * Coord, vous pouvez modifier le pointeur Coord comme le fait
realloc(), mais cette modification ne sortira pas de la fonction. En
revanche, si vous modifiez *Coord , ou *(Coord + N), cette modification
sera pérenne, observable depuis l'appelant après le retour.

Merci pour votre réponse.

Je souhaite que ma fonction test me renvoi la taille du nouveau tableau,
normalement la taille est déterminée à l'interieur de la fonction (pas dans
le test mais 'en vrai' oui).
D'après ce que vous me dites si je fais ça:

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

int test(double*);

int test(double* Coord, int taille)
{ int i;

taille++;
Coord = (double *)realloc(Coord,taille * 3 * sizeof(double));
/* ligne d'interet ci-apres */
for(i=3;i<6;++i) {*(Coord+i)=2.0;printf("Coord[%d] =
%fn",i+1,Coord[i]);}

return 0;
}

int main()
{
int taille, i,j, retour;
double *Coord;

taille =1;
Coord = (double *)malloc(3*sizeof(double));
for (i =0 ;i<3;++i) {Coord[i]=1.0;printf("Coord[%d] =
%fn",i+1,Coord[i]);}
retour = test(Coord,taille);
for(i=3;i<6;++i) printf("Coord[%d] = %fn",i+1,Coord[i]);

free(Coord);
return 0;

}
ça devrait marcher mais ça marche pas. Je ne comprends pas car normalement je
modifie bien ce qui l'y a à 'l intérieur' de ma case d'adresse Coord+i donc
ça devrait etre connu a l'exterieur de la fonction, non?


Vous recopiez du code avec toutes les erreurs, même celles que j'avais
corrigées. Compilez-vous vraiment en C89 ou supérieur ? En plus je
trouve que vous avez répondu un peu rapidement. Le code que je postais
n'étais pas génial, mais il fonctionnait, et ça valait sans doute le
coût de l'étudier un peu.

Le problème c'est que vous "perdez" ce que vous renvoie le realloc() de
la fonction. Ce realloc() libère Coord, ce qui fait que le free(Coord)
du main devient inutile et à comportement indéfini. Ce n'est pas le
seul problème loin de là.
Je ne vous donne que des pistes:
- Revoyez bien le manuel de realloc(), quitte à faire de petits tests
en afficchant par exemple les valeurs numériques des pointeurs (%p dans
printf()).
- Il vous faut impérativement récupérer le retour de realloc(). Vous
voulez également renvoyer un int. Vous avez donc deux prototypes à
votre disposition:

int test(double** double, int);

double* test(double*, int*)

--
Pierre Maurette


Avatar
Anthony Fleury

int test(double* Coord, int taille)
{ int i;

taille++;
Coord = (double *)realloc(Coord,taille * 3 * sizeof(double));
/* ligne d'interet ci-apres */
for(i=3;i<6;++i) {*(Coord+i)=2.0;printf("Coord[%d] =
%fn",i+1,Coord[i]);}

return 0;
}

ça devrait marcher mais ça marche pas. Je ne comprends pas car
normalement je modifie bien ce qui l'y a à 'l intérieur' de ma case
d'adresse Coord+i donc ça devrait etre connu a l'exterieur de la
fonction, non?


Devrait oui... Seulement l'exterieur ne connait pas la nouvelle valeur
de Coord, il ne connait que l'ancienne. Il faut donc qu'il sache où est
le tableau maintenant.

Pour que ca fonctionne, il faut passer un pointeur sur Coord :

int test(double** Coord, int taille)
{
int i;
taille++;
*Coord = (double *)realloc(*Coord,taille * 3 * sizeof(double));


...

Avec cela ca devrait fonctionner un peu mieux.

--
Anthony Fleury

Avatar
Pierre Maurette
(supersedes )

[...]
En C, on ne passe à une fonction que des copies de valeurs. L'argument de
la fonction devient dans la fonction une variable locale. Quand vous
passez double * Coord, vous pouvez modifier le pointeur Coord comme le
fait realloc(), mais cette modification ne sortira pas de la fonction. En
revanche, si vous modifiez *Coord , ou *(Coord + N), cette modification
sera pérenne, observable depuis l'appelant après le retour.

Merci pour votre réponse.

Je souhaite que ma fonction test me renvoi la taille du nouveau tableau,
normalement la taille est déterminée à l'interieur de la fonction (pas dans
le test mais 'en vrai' oui).
D'après ce que vous me dites si je fais ça:

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

int test(double*);

int test(double* Coord, int taille)
{ int i;

taille++;
Coord = (double *)realloc(Coord,taille * 3 * sizeof(double));
/* ligne d'interet ci-apres */
for(i=3;i<6;++i) {*(Coord+i)=2.0;printf("Coord[%d] =
%fn",i+1,Coord[i]);}

return 0;
}

int main()
{
int taille, i,j, retour;
double *Coord;

taille =1;
Coord = (double *)malloc(3*sizeof(double));
for (i =0 ;i<3;++i) {Coord[i]=1.0;printf("Coord[%d] =
%fn",i+1,Coord[i]);}
retour = test(Coord,taille);
for(i=3;i<6;++i) printf("Coord[%d] = %fn",i+1,Coord[i]);

free(Coord);
return 0;

}
ça devrait marcher mais ça marche pas. Je ne comprends pas car normalement
je modifie bien ce qui l'y a à 'l intérieur' de ma case d'adresse Coord+i
donc ça devrait etre connu a l'exterieur de la fonction, non?


Vous recopiez du code avec toutes les erreurs, même celles que j'avais
corrigées. Compilez-vous vraiment en C89 ou supérieur ? En plus je
trouve que vous avez répondu un peu rapidement. Le code que je postais
n'étais pas génial, mais il fonctionnait, et ça valait sans doute le
coût de l'étudier un peu.

Le problème c'est que vous "perdez" ce que vous renvoie le realloc() de
la fonction. Ce realloc() libère Coord, ce qui fait que le free(Coord)
du main devient inutile et à comportement indéfini. Ce n'est pas le
seul problème loin de là.
Je ne vous donne que des pistes:
- Revoyez bien le manuel de realloc(), quitte à faire de petits tests
en afficchant par exemple les valeurs numériques des pointeurs (%p dans
printf()).
- Il vous faut impérativement récupérer le retour de realloc(). Vous
voulez également renvoyer un int. Vous avez donc deux prototypes à
votre disposition:

int test(double** , int);

double* test(double*, int*);


--
Pierre Maurette


Avatar
Morgan Sangeux
Vous recopiez du code avec toutes les erreurs, même celles que j'avais
corrigées. Compilez-vous vraiment en C89 ou supérieur ?
Je ne suis sur de rien mais j'utilise dev-c++ et j'ai demandé de

compiler en C et ça compile.
En plus je
trouve que vous avez répondu un peu rapidement. Le code que je postais
n'étais pas génial, mais il fonctionnait, et ça valait sans doute le
coût de l'étudier un peu.
Je l'ai étudié, compris (enfin je pense) et vous remercie pour vos

efforts. Mais ça ne m'expliquait pas le fonctionnement qui conduisait
aux erreurs que j'obtenait.

Le problème c'est que vous "perdez" ce que vous renvoie le realloc() de
la fonction. Ce realloc() libère Coord, ce qui fait que le free(Coord)
du main devient inutile et à comportement indéfini. Ce n'est pas le seul
problème loin de là.
Je ne vous donne que des pistes:
- Revoyez bien le manuel de realloc(), quitte à faire de petits tests en
afficchant par exemple les valeurs numériques des pointeurs (%p dans
printf()).
- Il vous faut impérativement récupérer le retour de realloc(). Vous
voulez également renvoyer un int. Vous avez donc deux prototypes à votre
disposition:


double* test(double*, int*)
D'accord pour celui-là.


int test(double** double, int);
Je pense que celui-ci correspondrait plus à ce que je souhaite (modifier

mon tableau Coord (précision: potentiellement très très gros)dans la
fonction.
Encore merci pour vos efforts.

Avatar
Pierre Maurette
[...]
double* test(double*, int*)
D'accord pour celui-là.


int test(double** double, int);
Je pense que celui-ci correspondrait plus à ce que je souhaite (modifier mon

tableau Coord (précision: potentiellement très très gros)dans la fonction.
Ça ne change pas grand-chose. Tout au plus devrez-vous, quand vous

remplacerez "test" par un vrai nom, choisir ce dernier en accord avec
le type de retour. Sinon, c'est un choix d'habillage:

VarInt = test1(&Coord, VarInt);
ou
NewVarInt = test1(&Coord, VarInt);

ou
Coord = test2(Coord, &VarInt);

Sachez quand même qu'il faut au retour tester Coord par rapport à NULL.
La deuxième version est peut-être un peu mieux:

if((Coord = test(Coord, &VarInt)) != NULL) /* etc. */

--
Pierre Maurette


Avatar
Morgan Sangeux
Devrait oui... Seulement l'exterieur ne connait pas la nouvelle valeur
de Coord, il ne connait que l'ancienne. Il faut donc qu'il sache où est
le tableau maintenant.

Pour que ca fonctionne, il faut passer un pointeur sur Coord :

int test(double** Coord, int taille)
{
int i;
taille++;
*Coord = (double *)realloc(*Coord,taille * 3 * sizeof(double));


...

Avec cela ca devrait fonctionner un peu mieux.

ça fonctionne oui mais le comportement est 'étrange'.

Lorsque j'utilise ça:

int test(double **Coord, int taille)
{ int i;
double *bis;

*Coord = (double *)realloc(*Coord,6 * sizeof(double));
bis = *Coord;
for(i=0;i<6;++i) {bis[i] = 2.0;}

pas de probleme ça roule (dans le principal aussi).

Par contre si je fais ça:

int test(double **Coord, int taille)
{ int i;
double *bis;

*Coord = (double *)realloc(*Coord,6 * sizeof(double));
for(i=0;i<6;++i) {*Coord[i] = 2.0;}
Je me fait ejecter sauvagement.

Moi pas comprendre.

Avatar
Jean-Marc Bourguet
Morgan Sangeux writes:

Devrait oui... Seulement l'exterieur ne connait pas la nouvelle valeur de
Coord, il ne connait que l'ancienne. Il faut donc qu'il sache où est le
tableau maintenant.
Pour que ca fonctionne, il faut passer un pointeur sur Coord :
int test(double** Coord, int taille)
{
int i;
taille++;
*Coord = (double *)realloc(*Coord,taille * 3 * sizeof(double));
...
Avec cela ca devrait fonctionner un peu mieux.

ça fonctionne oui mais le comportement est 'étrange'.

Lorsque j'utilise ça:

int test(double **Coord, int taille)
{ int i;
double *bis;

*Coord = (double *)realloc(*Coord,6 * sizeof(double));
bis = *Coord;
for(i=0;i<6;++i) {bis[i] = 2.0;}

pas de probleme ça roule (dans le principal aussi).

Par contre si je fais ça:

int test(double **Coord, int taille)
{ int i;
double *bis;

*Coord = (double *)realloc(*Coord,6 * sizeof(double));
for(i=0;i<6;++i) {*Coord[i] = 2.0;}
Je me fait ejecter sauvagement.

Moi pas comprendre.


*Coord[i] se lit *(Coord[i]) pas (*Coord)[i]

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
Pierre Maurette
[...]
*Coord = (double *)realloc(*Coord,6 * sizeof(double));
for(i=0;i<6;++i) {*Coord[i] = 2.0;}
Pas le temps de vérifier, mais faites peut-être (*Coord)[i].


--
Pierre Maurette

1 2