cs_jb60
Messages postés55Date d'inscriptionmardi 16 septembre 2003StatutMembreDernière intervention 4 août 2008
-
21 oct. 2004 à 01:41
cs_djl
Messages postés3011Date d'inscriptionjeudi 26 septembre 2002StatutMembreDernière intervention27 novembre 2004
-
22 oct. 2004 à 18:53
Bonjour,
J'ai fait une source avec plusieurs fichier *.cpp et plusieurs fichiers *.h
Dans un fichier main.cpp, j'ai créé un pointeur BYTE *LesOctets;
Je n'ai donc à ce moment pas encore alloué d'espace pour la mémoire...
Je souhaite le faire par le biais d'une fonction (déclarée dans un autre fichier) qui a pour prototype
BOOL LectureFichier(char * NomDeFichier, BYTE *Buffer);
Dans laquelle je vais rentrer dans BYTE *Buffer le nom LesOctets.
C'est à dire qu'en utilisant cette fonction, je vais écrire (dans le fichier main.cpp ou est déclaré le pointeur BYTE *LesOctets):
LectureFichier(szFileName,LesOctets);
Durant cette fonction, je souhaite allouer de la mémoire pour le pointeur LesOctets, en faisant:
Buffer = new BYTE[tailleFichier] //TailleFichier étant calculée juste avant.
Dans la fonction, l'allocation de mémoire fonctionne parfaitement, mais lorsque je souhaite utiliser le pointeurs LesOctets dans le fichier main.cpp, le pointeur reste NULL. Je n'arrive donc pas à récupérer les octets que je viens de rentrer dans le pointeur LesOctets dans le fichier main.cpp.
Or, ceci doit être possible, comme on peut le trouver dans plusieurs fonctions standard du c++, telles que sprintf(szBuffer,"texte formatté",...);
Je ne sais pas comment faire, si quelqu'un peut m'aider, ça serait bien sympathique.
Je pourrais peut être donner mon code source pour exemple:
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Analyse les sélections de menu :
switch (wmId)
{
case IDM_FILE_OPEN:
if (PopFileOpenDlg(NULL,szFileName,szTitleName))
{
if (!LectureDuFichier(szFileName, LesOctetsDuFichier, &iFileSize))
MessageBox(hWnd,TEXT("Erreur lors de la lecture du fichier"),TEXT("Attention"),MB_OK);
else
{
//sprintf(TestBuffer,TEXT("Taille du fichier lue dans WinProc = %d"),iFileSize);
//MessageBox(NULL,TestBuffer,TEXT("Info"),MB_OK);
InvalidateRect(hWnd,NULL,TRUE);
}
}
break;
case IDM_ABOUT:
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
if (LesOctetsDuFichier!=NULL) //si on a rentré des données dans les octets à traiter
{
GetClientRect(hWnd,&rect);
MessageBox(hWnd,TEXT("Nous sommes dans le cas ou des données sont présentes dans le buffer des octets du fichier"),TEXT("Info"),MB_OK);
DrawText(hdc,(LPCTSTR) LesOctetsDuFichier,-1,&rect,DT_LEFT);
}
// TODO : ajoutez ici le code de dessin...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
HANDLE hFile=CreateFile(pFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile==INVALID_HANDLE_VALUE)
{
MessageBox(NULL,TEXT("Erreur de lecture du fichier spécifié, veuillez recommencer..."),TEXT("Erreur"),MB_OK);
return FALSE; //on sort de la fonction, car une erreur s'est produite
}
(*(TailleDuFichier))=GetFileSize(hFile,NULL);
//sprintf(TestBuffer,TEXT("Taille du fichier = %d"),(*(TailleDuFichier)));
//MessageBox(NULL,TestBuffer,TEXT("Info"),MB_OK);
if (nbreOfBytesRead<(*(TailleDuFichier)))
{
CloseHandle(hFile);
delete Buffer2;
return FALSE;
}
Buffer2[(*(TailleDuFichier))]='\0'; //on met le caractère nul à la fin du buffer
if (Buffer!=NULL) {MessageBox(NULL,"Erreur de buffer non nul","info",MB_OK); delete Buffer;}
sprintf(TestBuffer,TEXT("Adresse du buffer avant new = %X"),Buffer);
MessageBox(NULL,TestBuffer,TEXT("Info"),MB_OK);
Buffer = new BYTE[(*(TailleDuFichier))+1]; //on alloue de la mémoire pour le tableau de bytes utilisé dans WinProc
sprintf(TestBuffer,TEXT("Adresse du buffer après new = %X"),Buffer);
MessageBox(NULL,TestBuffer,TEXT("Info"),MB_OK);
for (unsigned int i=0;i<(*(TailleDuFichier));i++)
*(Buffer+i)=*(Buffer2+i); //On copie les données dans le buffer que l'on pourra utiliser dans WinProc
cs_aardman
Messages postés1905Date d'inscriptionmercredi 22 janvier 2003StatutMembreDernière intervention17 septembre 20123 21 oct. 2004 à 03:03
Salut,
Pour modifier une variable depuis une fonction, il faut passer la variable par adresse.
Meme logique pour les pointeurs: pour modifier un pointeur depuis une fonction, il faut passer le pointeur par adresse, c'est a dire un pointeur de pointeur.
ta func doit etre prototypée comme ca:
BOOL LectureFichier(char * NomDeFichier, BYTE ** Buffer);
et il faut passer &LesOctets en param.
et dans la fonction tu modifies Buffer:
*Buffer = ... ;
cs_djl
Messages postés3011Date d'inscriptionjeudi 26 septembre 2002StatutMembreDernière intervention27 novembre 20047 21 oct. 2004 à 20:02
jb60 > ya pas photo, utiliser les references c'est profiter d'un fabuleux outil offert par le c++
magic_Nono > alias 'pour' n'importe quel type je voulais dire, par exemple pour les tableaux multidim
entre
void f(int *n)
{
*n = 5;
}
...
f(&n);
et
void f(int &n)
{
n = 5;
}
...
f(n);
rien que sur cette exemple simplissime on voit tout de suite que le passage par pointeur sera source d'erreur alors qu'avec reference c'est completement transparent
HANDLE hFile=CreateFile(pFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile==INVALID_HANDLE_VALUE)
{
MessageBox(NULL,TEXT("Erreur de lecture du fichier spécifié, veuillez recommencer..."),TEXT("Erreur"),MB_OK);
return FALSE; //on sort de la fonction, car une erreur s'est produite lors de l'accès au fichier
}
(*(TailleDuFichier))=GetFileSize(hFile,NULL);
if (*Buffer!=NULL) {MessageBox(NULL,"Erreur de buffer non nul","info",MB_OK); delete Buffer;}
*Buffer = new BYTE[(*(TailleDuFichier))+1]; //on alloue de la mémoire pour le tableau de bytes utilisé dans WinProc
//sprintf(TestBuffer,TEXT("Nous sommes juste après ReadFile"));
//MessageBox(NULL,TestBuffer,TEXT("Info"),MB_OK);
if (nbreOfBytesRead<(*(TailleDuFichier)) )
{
MessageBox(NULL,TEXT("Attention, le buffer ne devrait pas etre delete"),TEXT("Erreur"),MB_OK);
CloseHandle(hFile);
delete *Buffer;
return FALSE; //on sort de la fonction
}
(*Buffer)[*(TailleDuFichier)]='\0'; //on met le caractère nul à la fin du buffer
CloseHandle(hFile);
return TRUE;
}
et en fait, lorsque j'utilise une première fois la fonction, c'est bon, ca marche, mais ensuite si je réutilise ma fonction, alors une adresse est présente dans LesOctets (représenté par Buffer dans la fonction). Donc je delete cette adresse, pour réallouer une zone mémoire avec assez d'espace pour contenir les prochaines données. Or, le programme plante lorsque je suis dans la boucle
if (*Buffer!=NULL) {MessageBox(NULL,"Erreur de buffer non nul","info",MB_OK); delete Buffer;}
comme si je ne pouvais pas delete le pointeur, alors que je l'ai initialisé précédemment avec l'opérateur new...
Si quelqu'un comprends cette erreur, je suis preneur de la réponse.
cs_jb60
Messages postés55Date d'inscriptionmardi 16 septembre 2003StatutMembreDernière intervention 4 août 2008 21 oct. 2004 à 20:54
Au fait djl,
Est-ce qu'avec un passage par référence on peut utiliser l'opérateur new et delete, comme avec des pointeurs?
Ou y'a t'il quelque chose de spécial à faire?
cs_djl
Messages postés3011Date d'inscriptionjeudi 26 septembre 2002StatutMembreDernière intervention27 novembre 20047 21 oct. 2004 à 21:02
oui, si tu passes un pointeur par reference
en gros, fais comme si c'etais un passage par valeur, sauf qu'au lieu de travailler sur un copie locale de la variable passer en argument, tu travailles directement dessus et tu peux donc la modifier
plus_plus_fab
Messages postés232Date d'inscriptionvendredi 9 janvier 2004StatutMembreDernière intervention 8 janvier 2005 21 oct. 2004 à 22:04
djl > ton exemple avec f(n), f(&n) est justement l'illustration du fait que les références ne se sont pas imposés (comme elles le méritent).
Si tu ne connais pas la déclaration de f, et que tu fais f(n), tu ne peux pas savoir si n peut éventuellement etre modifié. avec un appel f(&n), tu sais que si.
Sinon, la commodité d'écriture, je m'en moque un peu perso, mais c'est manifeste.
L'interet des références qui n'a pas été souligné, c'est que ça pointe constament vers qqchose. C'est comme un pointeur type *const ptr; auquel on applique l'indirection à chaque usage. C'est une information en plus pour le compilateur, qui lésine rarement à optimiser.
Ca évite aussi les erreurs, f(&n) avec un n non alloué, c'est le crash ...
f(n) forcément non (une référence est obligatoirement affecté à la déclaration)
cs_djl
Messages postés3011Date d'inscriptionjeudi 26 septembre 2002StatutMembreDernière intervention27 novembre 20047 21 oct. 2004 à 22:11
"Si tu ne connais pas la déclaration de f, et que tu fais f(n), tu ne peux pas savoir si n peut éventuellement etre modifié. avec un appel f(&n), tu sais que si."
ca se tient, pour une question de lisibilité, mais ca c'est un gros defaut du c++ tout ces mechanismes planqués
sinon comme tu l'as dit, un reference fais toujours references q qqchose et lors de la declaration elle doit etre initialisée
type& r = ...
en gros ca rejoins le faite que ca evite de faire des erreurs contrairement aux pointeurs qui en sont souvent la source
magic_Nono
Messages postés1878Date d'inscriptionjeudi 16 octobre 2003StatutMembreDernière intervention16 mars 2011 22 oct. 2004 à 14:08
Voici mis en mots ce que je cherchais à dire:
"Si tu ne connais pas la déclaration de f, et que tu fais f(n), tu ne peux pas savoir si n peut éventuellement etre modifié. avec un appel f(&n), tu sais que si."
C à l'usage des fonctions & a la relecture que C + claire avec des ptr: on sait de suite, sans voir la fonction si ses param sont modifiés.
Point final sur ce débat
Après, chacun utilise se qui lui semble le plus judicieux et quand on est sur un prj en commun, on fixe ces détails au départ.
Magicalement.
Magic Nono: l'informagicien! 8-)
PS G promis des prog a certain mais mon PC a fumé (carte mere & carte vidéos mortes... jutilise le portable entretemps..)
Des que C changé (pr mon ani probablement, je posterai tt ça)
Dslé ++
cs_djl
Messages postés3011Date d'inscriptionjeudi 26 septembre 2002StatutMembreDernière intervention27 novembre 20047 22 oct. 2004 à 18:53
magic_Nono > ...
"Si tu ne connais pas la déclaration de f, et que tu fais f(n), tu ne peux pas savoir si n peut éventuellement etre modifié. avec un appel f(&n), tu sais que si."
oui pour la lisibilité, entierement d'accord et c'est meme un defaut recurrent du c++
mais à l'usage non, absolument pas, si tu utilises une fonction sans savoir ce qu'elle fais, sans connaitre son prototype, t'es deja dans le mur
moi ce que je vois c'est que dans pratiquement tout les langages de haut niveau, les parametre sont in/out de maniere transparente