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

tableau a n dim et pointeurs de pointeurs

12 réponses
Avatar
Bonsoir j'essaie d'experimenter avec les pointeurs de pointeur et les
tableau a un dimension et je ne comprend pas vraiment pourquoi le petit
bout de code ci dessous fait un seg-fault dans une focntion mais marche
dans le main.

Si quelqu'un a un recapitulatif sur l'utilisation des tableau a n dim et
leur relatin avec les les poiunteur de pointeur je prends...

merci,
O.
=================================code =====================

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


void afficheall(char *** t);

int main(void){
int i,j;
char * t[3][3] ={
{"123","456","789"},
{"aze","rty","uio"},
{"wxc","vbn","jkl"}
};
/* ici Ok */
for (i=0;i<3;i++){
for (j=0;j<3;j++){
printf("-t,---%sA \n",*((*(t+i))+j));
/* printf("----%sB\n",*t[i]); */
/* printf("------%sB\n",*t[j]); */

}

}
/* la non ... Segmentation fault*/
afficheall(t);
return 0;
}

void afficheall(char *** t){
int i,j;
for (i=0;i<3;i++){
for (j=0;j<3;j++){
printf("-t,---%sA \n",*((*(t+i))+j));
// printf("----%sB\n",*t[i]);
//printf("------%sB\n",*t[j]);

}

}
}

10 réponses

1 2
Avatar
flure
Bonsoir j'essaie d'experimenter avec les pointeurs de pointeur et les
tableau a un dimension et je ne comprend pas vraiment pourquoi le petit
bout de code ci dessous fait un seg-fault dans une focntion mais marche
dans le main.


Parce qu'un seg-fault arrive toujours de manière aléatoire :)

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


void afficheall(char *** t);


wow ! effectivement, annoncé comme cela ça ne risque pas d'être simple :)

int main(void){
int i,j;
char * t[3][3] ={
{"123","456","789"},
{"aze","rty","uio"},
{"wxc","vbn","jkl"}
};
/* ici Ok */
for (i=0;i<3;i++){
for (j=0;j<3;j++){
printf("-t,---%sA n",*((*(t+i))+j));


pourquoi ne pas écrire simplement :
printf ("-t,---%sA n", t[i][j]);

Ta syntaxe est compliquée, donc source d'erreur. Je ne vérifie pas si
elle est juste, mais elle me paraît louche quand même ...




--
Florent "flure" C.
http://flure.free.fr

Avatar
Horst Kraemer
"@(none)" <""olivier"@(none)"> wrote:


Bonsoir j'essaie d'experimenter avec les pointeurs de pointeur et les
tableau a un dimension et je ne comprend pas vraiment pourquoi le petit
bout de code ci dessous fait un seg-fault dans une focntion mais marche
dans le main.

Si quelqu'un a un recapitulatif sur l'utilisation des tableau a n dim et
leur relatin avec les les poiunteur de pointeur je prends...

merci,
O.
=================================code ==================== >
#include<stdio.h>
#include<stdlib.h>


void afficheall(char *** t);

int main(void){
int i,j;
char * t[3][3] ={
{"123","456","789"},
{"aze","rty","uio"},
{"wxc","vbn","jkl"}
};
/* ici Ok */
for (i=0;i<3;i++){
for (j=0;j<3;j++){
printf("-t,---%sA n",*((*(t+i))+j));
/* printf("----%sBn",*t[i]); */
/* printf("------%sBn",*t[j]); */

}

}
/* la non ... Segmentation fault*/
afficheall(t);
return 0;
}

void afficheall(char *** t){
int i,j;
for (i=0;i<3;i++){
for (j=0;j<3;j++){
printf("-t,---%sA n",*((*(t+i))+j));
// printf("----%sBn",*t[i]);
//printf("------%sBn",*t[j]);

}

}
}


Un tableau de deux dimensions

toto t[7][10]

ne peut pas être représenté par un paramètre

void f(toto **p);

Seulement la première dimension se "transforme" en pointeur. Donc il
faut un paramètre

void f(toto (*p) [10]);

Dans ton cas

void afficheall(char * (*t)[3] );

ou bien

void afficheall(char * t[][3] );

ou bien

void afficheall(char * t[3][3] );


--
Horst

Avatar
Emmanuel Delahaye
livier"none" wrote on 03/02/05 :
#include<stdio.h>
#include<stdlib.h>

void afficheall(char *** t);

int main(void){
int i,j;
char * t[3][3] ={
{"123","456","789"},
{"aze","rty","uio"},
{"wxc","vbn","jkl"}
};
/* ici Ok */
for (i=0;i<3;i++){
for (j=0;j<3;j++){
printf("-t,---%sA n",*((*(t+i))+j));
/* printf("----%sBn",*t[i]); */
/* printf("------%sBn",*t[j]); */

}

}
/* la non ... Segmentation fault*/
afficheall(t);
return 0;
}

void afficheall(char *** t){
int i,j;
for (i=0;i<3;i++){
for (j=0;j<3;j++){
printf("-t,---%sA n",*((*(t+i))+j));
// printf("----%sBn",*t[i]);
//printf("------%sBn",*t[j]);

}

}


Erreur de type.

main.c: In function `main':
main.c:43: warning: passing arg 1 of `afficheall' from incompatible
pointer type

C'est pas char ***, c'est plutôt

#include <stdio.h>

void afficheall (char const *t[][3])
{
int i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf ("'%s'n", t[i][j]);
}
}
}

int main (void)
{
int i, j;
char const *t[3][3] {
{"123", "456", "789"},
{"aze", "rty", "uio"},
{"wxc", "vbn", "jkl"}
};

for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf ("'%s'n", t[i][j]);
}

}

afficheall (t);
return 0;
}

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++

Avatar

Erreur de type.

main.c: In function `main':
main.c:43: warning: passing arg 1 of `afficheall' from incompatible
pointer type

C'est pas char ***, c'est plutôt

#include <stdio.h>

void afficheall (char const *t[][3])
{
int i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf ("'%s'n", t[i][j]);
}
}
}

int main (void)
{
int i, j;
char const *t[3][3] > {
{"123", "456", "789"},
{"aze", "rty", "uio"},
{"wxc", "vbn", "jkl"}
};

for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf ("'%s'n", t[i][j]);
}

}

afficheall (t);
return 0;
}



Ok mais ca supose que tu connais le bonne du tabeleau au momment ou tu
ecris la fonction. Ce qui n'est pas tres modulaire, comment faire si je
veux mettre ma fonction dans module separer.
La taille du tableau passe en argument n'etant pas connue a priori mais
definie dans le main du fichier principal ?

O.

Avatar
screetch
none wrote:

Ok mais ca supose que tu connais le bonne du tabeleau au momment ou tu
ecris la fonction. Ce qui n'est pas tres modulaire, comment faire si je
veux mettre ma fonction dans module separer.
La taille du tableau passe en argument n'etant pas connue a priori mais
definie dans le main du fichier principal ?
gcc-only je crois (les specialistes te diront de quel standard ca fait

parie) :
int maFonction (void *parData, int parDim1, int parDim2)
{
typedef int Ligne[parDim1];
typedef Ligne Matrice[parDim2];
typedef Matrice *tableauA3Dimensions;

Matrice locMatrice = (Matrice *)parData;

return parData[1][0][5];
}

(en résumé, du typedef dynamique)


Sinon j'en profite pour reprendre ma vieille croisade contre la croyance
"tableau = pointeur", C'EST FAUX!!! Un pointeur s'utilise COMME un
tableau, mais un tableau de pointeur n'est pas equivalent a un tableau
de tableaux.

Dans ton cas, l'erreur vient du fait que tu utilises des tableaux de
pointeurs comme des tableaux de tableaux, or un tableau de tableaux a
quelque chose de plus : les données sont toutes packées dans l'ordre, et
tu peux caster un tableau multidimensionnel en tableau unidimensionnel.
Tu ne peux pas le faire avec un tableau de pointeurs car chaque case du
tableau principal contient non pas une valeur mais un pointeur

je vais tenter le dessin ascii

int **t
t
___
|ptr|->| 1 | 2 | 4 | 7 | 11 ...
|ptr|->| 2 | 8 |...
|ptr|
|ptr|
|ptr|
...

int t[3][3]
___________________________________
| 1 | 2 | 4 | 7 | 11| 18| -1| -2| -3|
-----------------------------------
`---+---' `---+---' `---+---'
t[1] t[2] t[3]
et donc tu peux caster ton tableau en tableau unidimensionnel. Pour
resoudre ton probleme, je te propose le code suivant (que je n'ai pas
teste, car je n'ai pas de compilateur sous la main) :


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


void afficheall(char *t);

int main(void){
int i,j;
char * t[3][3] ={
{"123","456","789"},
{"aze","rty","uio"},
{"wxc","vbn","jkl"}
};
/* ici Ok */
for (i=0;i<3;i++){
for (j=0;j<3;j++){
printf("-t,---%sA n",*((*(t+i))+j));
/* printf("----%sBn",*t[i]); */
/* printf("------%sBn",*t[j]); */

}
}
afficheall(&t[0][0]);/*adresse du premier element = adresse du debut
du tableau = char * ATTENTION ca ne marche que si t est un tableau
multidimensionnel!!! pas avec une declaration du type char ***t */
return 0;
}

/* tu peux donner a afficheall la taille d'une ligne
en appelant afficheall(&t[0][0], sizeof(t[0])); la j'ai mis 3 en dur */
/* note l'affichage est peut etre transposé, ou peut etre meme que ca
plante :p */
void afficheall(char *t){
int i,j;
for (i=0;i<3;i++){
for (j=0;j<3;j++){
printf("-t,---%sA n",*(t+3*i+j));
// printf("----%sBn",*t[i]);
//printf("------%sBn",*t[j]);

}

}
}

Avatar
screetch
screetch wrote:
none wrote:


Ok mais ca supose que tu connais le bonne du tabeleau au momment ou tu
ecris la fonction. Ce qui n'est pas tres modulaire, comment faire si
je veux mettre ma fonction dans module separer.
La taille du tableau passe en argument n'etant pas connue a priori mais
definie dans le main du fichier principal ?


gcc-only je crois (les specialistes te diront de quel standard ca fait
parie) :
int maFonction (void *parData, int parDim1, int parDim2)
{
typedef int Ligne[parDim1];
typedef Ligne Matrice[parDim2];
typedef Matrice *tableauA3Dimensions;

Matrice locMatrice = (Matrice *)parData;

return parData[1][0][5];
}

(en résumé, du typedef dynamique)


Sinon j'en profite pour reprendre ma vieille croisade contre la croyance
"tableau = pointeur", C'EST FAUX!!! Un pointeur s'utilise COMME un
tableau, mais un tableau de pointeur n'est pas equivalent a un tableau
de tableaux.

Dans ton cas, l'erreur vient du fait que tu utilises des tableaux de
pointeurs comme des tableaux de tableaux, or un tableau de tableaux a
quelque chose de plus : les données sont toutes packées dans l'ordre, et
tu peux caster un tableau multidimensionnel en tableau unidimensionnel.
Tu ne peux pas le faire avec un tableau de pointeurs car chaque case du
tableau principal contient non pas une valeur mais un pointeur

je vais tenter le dessin ascii

int **t
t
___
|ptr|->| 1 | 2 | 4 | 7 | 11 ...
|ptr|->| 2 | 8 |...
|ptr|
|ptr|
|ptr|
...

int t[3][3]
___________________________________
| 1 | 2 | 4 | 7 | 11| 18| -1| -2| -3|
-----------------------------------
`---+---' `---+---' `---+---'
t[1] t[2] t[3]
et donc tu peux caster ton tableau en tableau unidimensionnel. Pour
resoudre ton probleme, je te propose le code suivant (que je n'ai pas
teste, car je n'ai pas de compilateur sous la main) :


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


void afficheall(char *t);

int main(void){
int i,j;
char * t[3][3] ={
{"123","456","789"},
{"aze","rty","uio"},
{"wxc","vbn","jkl"}
};
/* ici Ok */
for (i=0;i<3;i++){
for (j=0;j<3;j++){
printf("-t,---%sA n",*((*(t+i))+j));
/* printf("----%sBn",*t[i]); */
/* printf("------%sBn",*t[j]); */

}
}
afficheall(&t[0][0]);/*adresse du premier element = adresse du debut
du tableau = char * ATTENTION ca ne marche que si t est un tableau
multidimensionnel!!! pas avec une declaration du type char ***t */
return 0;
}

/* tu peux donner a afficheall la taille d'une ligne
en appelant afficheall(&t[0][0], sizeof(t[0])); la j'ai mis 3 en dur */
/* note l'affichage est peut etre transposé, ou peut etre meme que ca
plante :p */
void afficheall(char *t){
int i,j;
for (i=0;i<3;i++){
for (j=0;j<3;j++){
printf("-t,---%sA n",*(t+3*i+j));
// printf("----%sBn",*t[i]);
//printf("------%sBn",*t[j]);

}

}
}


void afficheall(char **t), il manque une * (a vue de nez)


Avatar
Emmanuel Delahaye
livier"none" wrote on 04/02/05 :

void afficheall (char const *t[][3])


Ok mais ca supose que tu connais le bonne du tabeleau au momment ou tu ecris
la fonction. Ce qui n'est pas tres modulaire, comment faire si je veux mettre
ma fonction dans module separer.


Tu fais de la programmation générique.

http://mapage.noos.fr/emdel/tad.htm
http://mapage.noos.fr/emdel/clib.htm
Modules BLK, FSTR etc.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"


Avatar
Horst Kraemer
"@(none)" <""olivier"@(none)"> wrote:



Erreur de type.

main.c: In function `main':
main.c:43: warning: passing arg 1 of `afficheall' from incompatible
pointer type

C'est pas char ***, c'est plutôt

#include <stdio.h>

void afficheall (char const *t[][3])
{
int i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf ("'%s'n", t[i][j]);
}
}
}

int main (void)
{
int i, j;
char const *t[3][3] > > {
{"123", "456", "789"},
{"aze", "rty", "uio"},
{"wxc", "vbn", "jkl"}
};

for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf ("'%s'n", t[i][j]);
}

}

afficheall (t);
return 0;
}



Ok mais ca supose que tu connais le bonne du tabeleau au momment ou tu
ecris la fonction. Ce qui n'est pas tres modulaire, comment faire si je
veux mettre ma fonction dans module separer.
La taille du tableau passe en argument n'etant pas connue a priori mais
definie dans le main du fichier principal ?



void f(toto *p, size_t dim1, size_t dim2)
{

au lieu de p[i][j] il faut écrire ici

p[i*dim2+j] (0<=i<dim1, 0<=j<dim2)
};

toto a[3][7];
f((toto*)a,3,7);

Quand il s'agit d'un tableau de trois dimensions

void f(toto *p, size_t dim1, size_t dim2, size_t dim3)
{

/* p[i][j][k] -> p[(i*dim2+j)*dim3+k] */
}
toto a[3][7][9];
f((toto*)a,3,7,9);



pour quatre dimensions

void f(toto *p, size_t dim1, size_t dim2, size_t dim3, size_t dim4)
{

/* p[i][j][k][l] -> p[((i*dim2+j)*dim3+k)*dim4+l] */
}
toto a[3][7][9][2];
f((toto*)a,3,7,9,2);


etc...


--
Horst


Avatar
pat
Bonjour,

Voila un exemple de tableau de tableaux écrit en 5 minutes mais sans
plantage et sutout simple !
Alouer en dynamique et variable.

Compiler et tester sur TC2
C'est du C de base portable , le fichier "Alloc.h" s'apelle parfois
"malloc.h" sur certain compilo.
L'appel du nombre de tableaux est un "int" on pourrait mettre un long pour
une
"huge application" ou des "unsigned int" ou "unsigned long" chacun fera sa
propre cuisine...


Un bon exemple vaux mieux qu'un grand discours


pat









#include "stdio.h"
#include "alloc.h"


/* pointeur de tableau de tableau */
/* le seul ,l,ment Global */
/* les tableaux eux mSme sont sur le stack */
char far **TabDeTab;

int AllocTab(int , int);
void FreeTab( int );


main()
{
int i,t;
int nbTab;
int lenTab;

/* efface l'ecran */
clrscr();

/* 100 tableaux */
nbTab0;
/* de 255 char */
lenTab%5;

/* Allocation d'un tableau de 100 tableau de 255 char */
if (AllocTab(nbTab,lenTab) == -1)
printf("Erreur d'allocrn");
/*
exemple de prog utilisant les tableaux
*/

/* remplir 26 lignes de tableau */
for (t=0 ; t<26; t++) {
memset(TabDeTab[t],65+t,30); /* avec 30 a, b,c, etc.. */
TabDeTab[t][30] = '';
}
/* en afficher 20 */
for (t=0 ; t<20; t++) {
printf("%srn",TabDeTab[t]);
}

printf("Appuyer sur une touche pour lib,rer la m,moirern");
getchar();
/*
*/

/* sortir proprement en lib,rant */
FreeTab(nbTab);

printf("Termin, !rn Pas de plantagerntAppuyer sur une touche rn");
getchar();
}

/* ******************************************
Allocation dynamique d'un tableau de tableau
****************************************** */
int AllocTab(int nbTab, int lenTab)
{
int i;

TabDeTab = malloc( nbTab * sizeof(char far *));
for (i=0 ;i<nbTab; i++)
if( (TabDeTab[i] = malloc(lenTab)) == NULL) return(-1);

return(1);
}


/* ******************************************
lib,ration du tableau dynamique
****************************************** */

void FreeTab(int nbTab)
{
int i;
for (i=0 ;i<nbTab; i++)
free(TabDeTab[i]);

free(TabDeTab);

}
Avatar
Antoine Leca
En 42223417$0$11709$, pat va escriure:
Voila un exemple de tableau de tableaux écrit en 5 minutes mais sans
plantage et sutout simple !


Bien

Alouer en dynamique et variable.



Compiler et tester sur TC2


Bien. Et ailleurs ?

C'est du C de base portable ,


Non

le fichier "Alloc.h" s'apelle parfois "malloc.h" sur certain compilo.


Et <stdlib.h> à peu près partout. Y compris dans TC2.

L'appel du nombre de tableaux est un "int" on pourrait mettre un
long pour une "huge application"


?

ou des "unsigned int" ou "unsigned long" chacun fera sa propre cuisine...



Un bon exemple vaux mieux qu'un grand discours


Effectivement. L'exemple est très illustratif de ton discours, à défaut de
l'être de ton propos.


#include "stdio.h"
#include "alloc.h"


/* pointeur de tableau de tableau */
/* le seul ,l,ment Global */
/* les tableaux eux mSme sont sur le stack */
char far **TabDeTab;


Turbo C Version 2.01 Copyright (c) 1987, 1988 Borland International
Error fclc.c 9: Declaration syntax error

En dehors du fait que ce ne soit pas portable, c'est surtout la première
partie de la preuve que tu ne comprends pas ce que veulent dire les modèles
mémoires en programmation C sous DOS.


main()


C'est un détail sans importance, mais tu devrais prendre l'habitude de
mettre le type de retour, int.

/* efface l'ecran */
clrscr();


Undefined symbol '_clrscr' in module pat.c

for (t=0 ; t<26; t++) {
memset(TabDeTab[t],65+t,30); /* avec 30 a, b,c, etc.. */


Voici la seconde partie.

TabDeTab est un tableau de pointeurs long (far) vers des chaînes. Ici, tu
initialises (avec un code très tordu et mal commenté, mais c'est vraiment de
l'anecdote) des pointeurs « normaux » (pour le modèle en cours).


printf("%srn",TabDeTab[t]);


Même problème.


printf("Appuyer sur une touche pour lib,rer la m,moirern");


r est inutile.

getchar();


Une touche ne suffira pas, il faudra probablement appuyer sur la touche
Intro pour obtenir le moindre effet...

for (i=0 ;i<nbTab; i++)
if( (TabDeTab[i] = malloc(lenTab)) == NULL) return(-1);


Et voici la troisième partie.
Ici, tu utilises malloc(), donc là encore des pointeurs « normaux ». De
fait, cela veut dire que le code dans main() va *apparement* fonctionner,
car tout le programme utilises les pointeurs normaux même s'il prétend
utiliser des pointeurs longs. Mais si tu augmentes un peu la taille de ton
tableau, disons jusqu'à 250 lignes, ton programme va se plaindre pour «
erreur d'alloc », alors qu'en fait il te reste plein de mémoire disponible,
il suffit simplement de savoir aller la chercher.


Antoine

1 2