Bonjour, j'essaye d'afficher mon tableau 2D en utilisant une fonction mais mon code ne compile pas. J'ai chercher sur plusieurs forum mais je n'arrive pas a trouver la solution. Je pense qu'il faut cree un pointeur vers mon tableau 2D mais je ne sais pas comment m'y prendre, voici mon code :
En général c'est une question de style - un avantage de char tab[][W] c'est que ça implique a priori que ce n'est pas qu'un pointeur de tableau. Après personnellement je n'écris jamais tab[][W] je préfère mettre **tab parce que j'y vois plus clair comme ça (par contre je perds l'info statique que la taille des lignes de tab est W)
EDIT : comme l'a indiqué rouloude, ce que je viens de dire est une grosse bêtise
- Edité par potterman28wxcv 27 juin 2019 à 17:27:06
En général c'est une question de style - un avantage de char tab[][W] c'est que ça implique a priori que ce n'est pas qu'un pointeur de tableau. Après personnellement je n'écris jamais tab[][W] je préfère mettre **tab parce que j'y vois plus clair comme ça (par contre je perds l'info statique que la taille des lignes de tab est W)
Ce n'est pas une question de style : tab[][W] n'est pas équivalent à **tab ,
Un pointeur sur tableau n'est pas un pointeur sur pointeur !
En général c'est une question de style - un avantage de char tab[][W] c'est que ça implique a priori que ce n'est pas qu'un pointeur de tableau. Après personnellement je n'écris jamais tab[][W] je préfère mettre **tab parce que j'y vois plus clair comme ça (par contre je perds l'info statique que la taille des lignes de tab est W)
Ce n'est pas une question de style : tab[][W] n'est pas équivalent à **tab ,
Un pointeur sur tableau n'est pas un pointeur sur pointeur !
Oui tu as tout à fait raison ! Mea culpa. ça n'a jamais été mon fort les tableaux à plusieurs dimensions.
Est-ce que ces deux codes sont équivalents selon toi ? J'ai essayé de regarder l'assembleur généré mais je n'arrive pas à m'en convaincre
#define SY 100
int f(int *t, int sx){
int S = 0;
int i, j;
for (i = 0 ; i < sx ; i++){
for (j = 0 ; j < SY ; j++){
S += t[SY*i+j];
}
}
return S;
}
int g(int t[][SY], int sx){
int S = 0;
int i, j;
for (i = 0 ; i < sx ; i++){
for (j = 0 ; j < SY ; j++){
S += t[i][j];
}
}
return S;
}
Oui, les 2 fonctions font la même chose, elles additionnent sx lignes de SY entiers consécutifs. Il y a quand même une différence, le premier paramètre à passer est différent - du moins par le type, mais pas par sa valeur. Et selon toi, la fonction suivante est-elle équivalente, et peut-elle être une optimisation de ton code?
int h( const int *t, int sx ) {
int S = 0;
for ( const int* fin = t+sx*SY ; t<fin ; ++t ) {
S += *t;
}
return S;
}
La différence que je vois c'est que tu utilises une seule boucle for au lieu de deux - et tu utilises une variable de moins vu que tu n'as qu'une boucle for au lieu de deux. Par contre c'est pas du tout lisible je trouve, j'aurais personnellement écrit ça plutôt comme ceci :
int h2( const int *t, int sx ) {
int S = 0;
for ( int i = 0 ; i < sx*SY ; i++ ) {
S += t[i];
}
return S;
}
Par rapport à toi j'utilise deux temporaires en plus (à la louche) mais au moins ce que la fonction fait est clair.. J'ai tendance à préférer la clarté à la performance (enfin, à partir du moment où ça ne modifie pas la complexité bien sûr).
Bon, j'ai été un peu curieux de mesurer tout ça, donc j'ai fait ce programme :
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#define SY 1000
#define SX 1000
#define REPEAT 10000
int f(const int *t, int sx){
int S = 0;
int i, j;
for (i = 0 ; i < sx ; i++){
for (j = 0 ; j < SY ; j++){
S += t[SY*i+j];
}
}
return S;
}
int g(const int t[][SY], int sx){
int S = 0;
int i, j;
for (i = 0 ; i < sx ; i++){
for (j = 0 ; j < SY ; j++){
S += t[i][j];
}
}
return S;
}
int h( const int *t, int sx ) {
int S = 0;
for ( const int* fin = t+sx*SY ; t<fin ; ++t ) {
S += *t;
}
return S;
}
int h2( const int *t, int sx ) {
int S = 0;
for ( int i = 0 ; i < sx*SY ; i++ ) {
S += t[i];
}
return S;
}
void test_and_print(char *s, int (*func)(const int *, int), int *t, int sx, bool dry_run){
clock_t start, stop;
int val;
int i;
start = clock();
for (i = 0; i< REPEAT; i++)
val = func(t, sx);
stop = clock();
if (dry_run)
return;
printf("%s execution\n", s);
printf("\tValue: %d\n", val);
printf("\tTime: %ld\n", (stop-start)/REPEAT);
}
int main(void){
srand(time(NULL));
int t[SX][SY];
for (int i = 0; i < SX; i++)
for (int j = 0; j < SY; j++)
t[i][j] = rand();
test_and_print("h2", h2, t, SX, true);
test_and_print("f", f, t, SX, false);
test_and_print("g", g, t, SX, false);
test_and_print("h", h, t, SX, false);
test_and_print("h2", h2, t, SX, false);
return 0;
}
Je compile en -g -std=c99 -O3 -Wall. Et j'ignore bien gentiment les warnings que ça me donne Le compilo me fait bien savoir qu'un "int *" et un "int (*)[1000]" ce n'est pas la même chose.
Ce programme va donc répéter 10000 fois le calcul, sur un tableau de 1000*1000
Je répète ce programme 3 fois, ça donne :
[sixcy@margeriaz:oc] ./2dsum
f execution
Value: 1226605698
Time: 199
g execution
Value: 1226605698
Time: 200
h execution
Value: 1226605698
Time: 203
h2 execution
Value: 1226605698
Time: 195
[sixcy@margeriaz:oc] ./2dsum
f execution
Value: -1192628864
Time: 202
g execution
Value: -1192628864
Time: 198
h execution
Value: -1192628864
Time: 205
h2 execution
Value: -1192628864
Time: 194
[sixcy@margeriaz:oc] ./2dsum
f execution
Value: -457814823
Time: 195
g execution
Value: -457814823
Time: 198
h execution
Value: -457814823
Time: 201
h2 execution
Value: -457814823
Time: 195
La fonction h2 a l'air plus optimisée que les autres de quelques cycles mais c'est pas très marqué non plus. ça fait gagner 3% peut-être ?
A noter que si mon tableau est maintenant de 10000 * 1000, je me tape une segmentation fault au niveau du srand(time(NULL)), je penche pour un problème de stack étant donné que ça fait 40 MB allouées sur la stack mais je n'ai pas creusé plus loin..
- Edité par potterman28wxcv 28 juin 2019 à 10:35:44
L'erreur dans mon code est justement d'avoir multiplié les valeurs au lieu de 2 boucles. Car rien ne dit que le produit de 2 int tient dans un int. Les 4 fonctions devraient avoir un code optimisé donnant exactement la même durée, les 2 dernières devraient être égales et mais légèrement différentes des 2 premières pour leur ajouter le bug sur les très grands tableaux. Es-tu sûr d'avoir compilé en Release avec les optimisations en vitesse?
L'erreur dans mon code est justement d'avoir multiplié les valeurs au lieu de 2 boucles. Car rien ne dit que le produit de 2 int tient dans un int. Les 4 fonctions devraient avoir un code optimisé donnant exactement la même durée, les 2 dernières devraient être égales et mais légèrement différentes des 2 premières pour leur ajouter le bug sur les très grands tableaux. Es-tu sûr d'avoir compilé en Release avec les optimisations en vitesse?
J'ai compilé en -O3. Pour un utilisateur d'un IDE type Code::Block ça revient effectivement à compiler en Release avec "les optimisations de vitesse".
Je ne vois pas de multiplications dans ton code - et quand tu fais ++t tu incrémentes le pointeur t d'une "case" de int, donc tout va bien ?
Tu peux tester sur ta machine avec tes propres options de compilation pour voir si t'en viens à la même conclusion que moi
- Edité par potterman28wxcv 28 juin 2019 à 21:31:31
Problème pointeur sur tableau 2D
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
En recherche d'emploi.
En recherche d'emploi.