Jump to content

SUBIECTE NOI
« 1 / 5 »
RSS
Jante noi shitbox

Trinitas TV 4K

Dacia 1316 cu 6 usi ...

Frecventa modificata radio
 Un nou pericol pt batrani

Ar trebuii sa vindem imobiliarele...

Dupa renuntarea la aparat dentar

pelerinaj in Balcik
 Noul format Jpegli iși propu...

Dade, dade

Probleme accesare nr test telefon

Parola la lock screen
 Deparazitare externa pisici fara ...

Seriale turcesti/coreene online H...

Merita un Termostat Smart pentru ...

Sfat achizitie MTB Devron Riddle
 

pointeri

- - - - -
  • Please log in to reply
192 replies to this topic

#19
neagu_laurentiu

neagu_laurentiu

    Guru Member

  • Grup: Senior Members
  • Posts: 40,604
  • Înscris: 30.07.2003
Inseamna ca ai inteles.
Tu de ce ai pus la fel in "int *a=(int*)malloc(...)" ? Adresa mea in hexa e exact ce returneaza malloc.

Daca ai char *p si int * p care e diferenta ?

Edited by neagu_laurentiu, 26 June 2010 - 14:07.


#20
vali38

vali38

    Active Member

  • Grup: Members
  • Posts: 1,845
  • Înscris: 16.10.2005

View Postneagu_laurentiu, on 26th June 2010, 15:03, said:

Daca ai char *p si int * p care e diferenta ?
diferenta este intre memoria alocata pentru char (1 byte) si pentru int (4 bytes)

#21
neagu_laurentiu

neagu_laurentiu

    Guru Member

  • Grup: Senior Members
  • Posts: 40,604
  • Înscris: 30.07.2003

View Postvali38, on 26th June 2010, 15:23, said:

diferenta este intre memoria alocata pentru char (1 byte) si pentru int (4 bytes)
Nu. Oarecum.
[][][][][][][][][][][][] - astia-s octetii de memorie. Poti descrie ?

#22
vali38

vali38

    Active Member

  • Grup: Members
  • Posts: 1,845
  • Înscris: 16.10.2005
nu sunt sigur. stiu ca intr-un octet se poate reprezenta un singur caracter sub forma binara. pe fiecare dintre acei octeti va veni cate un caracter

Edited by vali38, 26 June 2010 - 14:34.


#23
neagu_laurentiu

neagu_laurentiu

    Guru Member

  • Grup: Senior Members
  • Posts: 40,604
  • Înscris: 30.07.2003
[	] [	] [	] [	] [	] [	] [	]
0x0010 0x0011 0x0012 0x0013 0x0014 0x0015 0x0016

char* p = (char* p) 0x0010
va face referire la:
[	]
0x0010
iar pentru p = p+1 rezulta referirea la 0x0011


int* p = (int* p) 0x0010
va face referile la:
[	] [	] [	] [	]
0x0010 0x0011 0x0012 0x0013
iar pentru p = p+1 rezulta referirea la 0x0014

Edited by neagu_laurentiu, 26 June 2010 - 14:50.


#24
m3th0dman

m3th0dman

    Senior Member

  • Grup: Senior Members
  • Posts: 9,269
  • Înscris: 03.01.2007
Pentru a înțelege pointerii este necesar prima dată să înțelegi variabilele.

În C&C++ o variabilă este o structura de date care are 4 câmpuri. Să luăm ca exemplu variabila int x=5; .
Cele 4 câmpuri sunt:
1.Nume - în cazul de față x;
2.Valoare - în cazul de față 5;
3.Tip - în cazul de față int.
4.Adresă - reprezintă locația unde a fost alocată memoria. Pentru a o afla aplici operatorul de referențiere (&), deci în cazul de față adresa e &x; fiind începător nu te interesează valoarea adresei.

Acum variabilele normale au ca valoare ceva numere concrete, care sunt utile și sunt folosite de utilizator.
Pointerii de fapt sunt tot variabile (adică au tot aceste 4 tipuri) dar care la valoare în loc de ceva util, au adresa spre o variabilă (sau o adresă special alocată - malloc) care are ceva util.

Șmecheria este că valoarea unui pointer nu trebuie să aibă neaparat adresa unei alte variabile (asta n-am priceput-o din prima). Poate avea orice adresă care este special alocată pentru a stoca valori utile (adresă ce este returnată funcțiile malloc, calloc, realloc).
Diferența principală între pointeri și variabile este la declarare. O variabila o declari și ai tot ce-ți trebuie pentru ea (toate cele 4).
Dar un pointer îl declari, dar nu are valoare deoarece la valoare trebuie o adresă.
De aceea nu are sens să scrii direct:
int *p=5;
Adică, nume are (p), tip are (int) și adresă are (nu te interesează) dar ca valoare nu are nimic și tu-l obligi ca în adresa nimic să scrie 5.

Corect ar fi:
int *p;
p=malloc(sizeof(int));//acum p are ca valoare adresa returnată de malloc
*p=5;//deci are unde pune 5

sau
int *p,i;
p=&i;//p are valoare adresa lui i;
*p=5;//ceea ce implică faptul că valoare lui i e 5


Acum la cealaltă întrebare, să încerc să-ți răspund.
Să presupunem că trebuie să faci un program care să-ți stocheze într-un vector n numere (n nu se dă); citirea se termină când întâlnești primul 0. Tu știi că n poate fi maxim 5000, dar de cele mai multe ori n este mai mic decât 100.
În programarea normală tu trebuie să declari un vector de 5000 și de cele mai multe ori să lași 4900 de elemente nefolosite (risipă mare de memorie).
Dar cu pointeri ai ceva de genul:
int *x,i=0;//declari pointerul
x=malloc(sizeof(int));//dai o valoare pointerului declarat - aloci memorie pentru primul element
do
{
scanf("%d",x+i);//x+i == &(*(x+i)) == &x[i]
i++;
x=realloc(x,(i+1)*sizeof(int));/*aloci memorie pentru încă un element din x, zona de memorie fiind alocată consecutiv și automat (compilatorul știe de câți biți ai nevoie în plus)*/
}
while(x[i-1]!=0);
int k;
for(k=0;k<i;k++)
printf("%d ",x[k]);

Astfel dacă ai 65 de elemente, vei folosi memorie doar pentru 65 de elemente, iar dacă ai 4800 de elemente vei folosi memorie pentru 4800. Acesta este doar un avantaj al pointerilor (pe lângă multe altele).

Edited by m3th0dman, 30 June 2010 - 20:18.


#25
webulxpert

webulxpert

    Senior Member

  • Grup: Senior Members
  • Posts: 2,065
  • Înscris: 28.09.2006
dar cum pot afla cata memorie a fost rezervata pentru un pointer?

adica:

int *x = (int*) malloc(10*sizeof(int));

malloc a rezervat 40 Byte pentru *x.

sizeof(x) returneaza 4.

si de ce cand initializam *x cu o adresa trebuie adresa sa o convertim sa fie de acelas tip ca *x , (int*) malloc(10); ?

altceva:

 int *p = (int*) 0x000A;
	printf("val = %d\n",p);
	p = (int*) 1;
	printf("val = %d\n",p);
	printf("size = %d\n",sizeof(p));

out:
val = 11
val = 1
size = 4

cum prima data p are valoare 11 daca are doar adresa atribuita? (atiu ca A in hex = 11).
de ce este necesar sa pun (int*) la p = 1? (int*) converteste in adresa pentru int ? de ce trebuie ?

iar segmentation fault ce inseamna?

primesc eroare cand execut codul:

  int i=0;
	char *c = (char*)malloc(sizeof(char));
	ifstream myfile;
	myfile.open("fisier.txt");

	while( ! myfile.eof())
	{
		i++;
		c[i] = myfile.get();
		c = (char*) realloc(c,(i+1)*sizeof(char));
	}

	for(int j=0; j<i; j++)
	{
		printf("%s",c[j]);
	}

Edited by webulxpert, 01 July 2010 - 19:15.


#26
msmihai

msmihai

    Senior Member

  • Grup: Senior Members
  • Posts: 5,271
  • Înscris: 02.09.2006

Quote

dar cum pot afla cata memorie a fost rezervata pentru un pointer?

din moment ce tu ai scris programul si stii dimensiunea tipurilor de baza, stii cata memorie a fost alocata.

Quote

si de ce cand initializam *x cu o adresa trebuie adresa sa o convertim sa fie de acelas tip

malloc intoarce pointer de tip void*. daca nu ai void* si in stanga , faci cast. asa functioneaza C.

la ultima faza habar n-am ce vrei sa faci. iti declari un pointer catre adresa 0xA din memorie. poti sa o faci simplu int*  p = 0xa;
vrei sa afisezi ce se gaseste la adresa 0xA ? deferentiezi pointerul. adica printf("%d",*p);

segmentation fault apare cand incerci sa accesezi o zona de memorie care nu permite accesul sau incerci sa scrii peste o zona read-only, samd.

Edited by msmihai, 01 July 2010 - 19:25.


#27
webulxpert

webulxpert

    Senior Member

  • Grup: Senior Members
  • Posts: 2,065
  • Înscris: 28.09.2006
daca fac printf("%d",*p) primesc segmentation fault.

daca am inteles corect:

*p = aici atribuit adresa
p = atribui valoare care se retine in adresa
&p - este adresalui *p

da?

cu int *c = (int*) malloc(10*4);

daca vreau sa atrbui o valoare pentru primii 4 biti lui c,

fac
c = (int*) val (pentru ce trebuie (int*)? [la malloc am inteles pentru ce]).
urmatorii 4 biti sunt
c[1]
sau
c+1 ?

daca vreau sa atribui pentru urmatorii 4 biti cum fac?

#28
gnomemory

gnomemory

    Junior Member

  • Grup: Members
  • Posts: 59
  • Înscris: 12.12.2007
@webulxpert
S-ar putea sa te bag de tot in ceata, dar legat de intrebarea ta:

a[i] este echivalent cu *(a+i), dar si cu i[a]
a[i][j] este echivalent cu *(*(a+i)+j)


Iar cand aloci un int, evita sa hardcodezi dimensiunile tipului (dimensiunea lui int poate sa varieze. De aceea te adaptezi, folosind sizeof() . sizeof() returneaza dimensiunea unui tip).
Scrierea cea mai eleganta e :

int *c = (int*) malloc(sizeof(*c));

Acum s-ar putea sa nu intelegi ce e *c de la sizeof().
Si cu speranta ca nu te vei afunda si mai mult in ceata:
: int *c - atunci sizeof(*c) este echivalent cu sizeof(int) (deoarce *c are tipul int);
: int **c - atunci sizeof(**c) este echivalent cu sizeof(int) (deoarece **c va avea tipul int);
: int **c - atunci sizeof(*c) este echivalent cu sizeof(int*) (deoarece *c va avea tipul int*);
: int **c - atunci &c va avea tipul int***
: int ***c - atunci &c va avea tipul int**** , etc.


Si ca nota suplimentara, in C nu e indicat sa faci niciodata cast la un tip dupa ce ai aplicat malloc.
Astfel ca daca folosesti C:
int *c = malloc(sizeof(*c));


Iar daca folosesti C++:
int *c = (int*) malloc(sizeof(*c));

Apropos de Cast uite aici o dezbatere: http://stackoverflow...esult-of-malloc

Iar acum la intrebarea ta:

Quote

*p = aici atribuit adresa
p = atribui valoare care se retine in adresa
&p - este adresalui *p

*p indica valoarea int care se afla la adresa unde indica p.
p adresa propriu-zisa unde indica p.
&p adresa lui p.

Exemplu de cod:
int x = 3;
int *y = malloc(sizeof(*y));
y = &x;  /* y pointeaza catre adresa lui x */
printf("%d\n", *y); /* Afiseaza 3 deoarece asta e valoarea lui x */
printf("%d\n", y);  /* Adresa lui x de pe stack */
printf("%d\n", &y); /* Adresa lui y de pe heap */
*y = 5; /* Schimbam valoarea zonei de memoriei unde pointeaza y, adica zona de memorie x */
printf("%d", x); /* Afiseaza 5 */
pritntf("%d",*y); /* Afiseaza 5 */

Edited by gnomemory, 01 July 2010 - 20:22.


#29
webulxpert

webulxpert

    Senior Member

  • Grup: Senior Members
  • Posts: 2,065
  • Înscris: 28.09.2006
cu int** si int*** nu am prea inteles, ce sunt pointeri la pointeri ?

iar cu

a[i] = *(a+i) am inteles cred, a este adresa iar peste i "pasi" se afla valoarea care o caut eu.

dar cu i[a] nu am inteles, daca i=1, a=0x1 -> 1[0x1] ce face compilatorul aici nu inteleg.

#30
gnomemory

gnomemory

    Junior Member

  • Grup: Members
  • Posts: 59
  • Înscris: 12.12.2007

View Postwebulxpert, on 1st July 2010, 21:37, said:

cu int** si int*** nu am prea inteles, ce sunt pointeri la pointeri ?

iar cu

a[i] = *(a+i) am inteles cred, a este adresa iar peste i "pasi" se afla valoarea care o caut eu.

dar cu i[a] nu am inteles, daca i=1, a=0x1 -> 1[0x1] ce face compilatorul aici nu inteleg.

Ok, am sa incerc sa o iau cu inceputul.
Primul lucru care trebuie sa-l intelegi cand incepi sa lucrezi cu pointeri este sa faci diferenta dintre heap si stack.

1. Stack si Heap
a) Stack - este o zona din memorie care este folosita pentru stocarea variabilelor locale. Cand spun variabile locale ma refer la variabilele "din interiorul functiilor". O variabila locala are sens, atata vreme cat o tin acoladele :P. Uite ca sa intelegi la ce ma refer:
void functie(){
	int x = 5; /* Aici "se naste" x */
	printf("%d",x); 
	/* De aici incolo x nu mai are sens */
}
Cand spun ca x nu mai are sens, ma refer la faptul ca sub nici un fel nu te vei mai putea referi vreodata la x-ul ala sau la zona de memorie pe care el a ocupat-o candva. Memoria de pe stack nu este gestionata de tine, astfel incat nu trebuie sa iti faci vreodata griji ce s-a intamplat cu ea.
Pe langa asta tine minte ca cele doua acolade definesc cat de mult va trai o variabila.
Uite un exemplu mai complex:
void functie(){
	int x = 5;
	{
		int y;
		y = 5;
		/* Dupa inchiderea acoladei y isi pierde sensul */
	}
	printf("%d",x);
	printf("%d",y); /* Nu va functiona, deoarece nu se mai stie cine a fost y */
}
Timpul de acces pentru stack e mic (adica zona aceasta de memorie este accesata rapid), insa mare problema e ca limitat. Atunci cand vei ocupa tot stack-ul vei primi eroarea Stack Overflow.

B) Heap Este o zona de memorie imensa, gestionata de "heap allocator" adica rutinele care se gasesc in spatele malloc, realloc, calloc etc. E o zona de memorie unde timpul de acces e mai mare, si unde programatorul are grija sa o gestioneze. Adica tot ce a alocat va trebui sa de-aloce. La zonele de memorie de pe heap te vei adresa prin pointeri.

2. La ce sunt buni pointeri
- In primul rand reprezinta metoda prin care te adresezi la zonele alocate pe heap.
- Un alt lucru important e legatura dintre pointeri si tablourile unidimensionale (array-uri).
In plus C-ul este pass by value. Ce inseamna pass by value ? Sa luam exemplul urmator:
#include <stdio.h>
#include <stdlib.h>

void functie(int x){
	x = 5;
}

int main(int argc, char** argv) {
	int x = 2;
	functie(x);
	printf("%d\n",x); /* Afiseaza 2 */
	return (0);
}
Functia "functie" nu va avea nici un efect asupra lui x, adica va fi afisat tot 2. Asta se intampla deoarece x-ul care ajunge in corpul functiei este o "copie" a x-ul pasat, copie care va primi valoarea 5 si care din pacate isi va incheia existenta dupa inchiderea ultimei acoladate a functiei "functie".
Solutia pentru asta va fi sa folosesti un pointer, adica sa lucrezi cu zona de memorie a lui x, in loc sa trimiti direct valoarea lui x.
void functie(int *x){ /* Pasezi o adresa catre un int */
	*x = 5; /* Ii schimbi valoarea int-ului la care se face referire in 5 */
}

int main(int argc, char** argv) {
	int x = 2;
	functie(&x); /* Pasezi functiei adresa in loc de valoarea propri-zisa */
	printf("%d\n",x); /* Afiseaza 5 */
	return (0);
}

3) Legatura dintre pointeri si tablouri (array-uri).
Asta e strict legat de intrebarea ta.
Sa luam programul urmator:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
	int i;
	double d1[4]; /* Un tablou unidimensional aflat pe stack
				   de dimensiune 4*/
	double *d2 = malloc(sizeof(double) * 10); /* Un tablou unidimensional pe 
											   * heap de dimensiune 4*/

	for(i = 0; i < 4; ++i){
		d1[i] = i;
		d2[i] = i;
	}
	
	while(i-->0){
		printf("%2.2f\n",d1[i]);
		printf("%2.2f\n",d2[i]);
		printf("\n");
	}

	return (0);
}
Dupa cate observi d1 este un tablou de double-uri de dimensiune 4, iar d2 este o zona de memorie in care poti sa scrii 4 double-uri. Forma de adresare e initial aceeasi d2[k],  iti returneaza al k-elea double din zona de memorie.
Nu uita insa ca d2 este un pointer;
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
	int i;
	double *d2 = malloc(sizeof(double) * 10); /* Un tablou unidimensional pe 
											   * heap de dimensiune 4*/

	for(i = 0; i < 4; ++i){
		d2[i] = i;
	}

	printf("%2.2f\n",*d2); /* Afiseaza primul double din zona de memorie spre care
						  * pointeaza d2 */
	printf("%2.2f\n",*(d2+1)); /* Afiseaza al doilea double din zona de memorie spre
							care pointeaza d2 . IMPORTANT: "1" din paranteza nu e
							  un numar ci o unitate. Poti sa-l privesti ca un fel
							  de index */
	printf("%2.2f",*(d2+89999)); /* Probabil Segmentation Fault, deoarece ai iesit din zona
							  * alocata lui d2 */

	return (0);
}
Daca te uiti acum pe ambele programe, o sa observi o similitudine:
d2[1] e acelasi lucru cu *(d2+2), dar adunarea e comutativa, si e astfel si acelasi lucru cu *(2+d2), care e acelasi lucru cu 2[d2] . Exemplul asta e extrem, deoarece nici un programator sanatos la cap nu ar folosi o notatie 2[d2]. In schimb scoate foarte bine in evidenta relatia dintre pointeri si tablourile unidimensionale. Asta ca sa iti raspund la prima intrebare.

4) Tablouri bidimensionale - pointeri la pointeri.
int** inseamna intr-adevar pointer la pointer. Iar lucrul asta e excelent deoarece astfel poti sa simulezi o matrice.
Uite aici, am mai vorbit despre pointeri la pointeri: http://www.skullbox....68334/#msg68334

Edited by gnomemory, 01 July 2010 - 21:50.


#31
webulxpert

webulxpert

    Senior Member

  • Grup: Senior Members
  • Posts: 2,065
  • Înscris: 28.09.2006
multumesc pentru tutorial. am inteles mai multe lucruri si mi-am schimbat putin parerea despre pointeri.

d2 - nu are rezarvata memorie pentru 10 cifre double ? (in loc de 10 cred ca ai scris 4)

am citi lectia 8 din linkul care mi-ai dat dar ca sa fiu sigur mai intreb odata.

am impresia ca daca folosim:
*p = 2;
*(p+1) = 3;

ar trebui sa folosim si
*p[2] = 4;

dar asta e.

nu am prea inteles cum aflu cata memorie a fost rezervata pentru un pointer, adica folosec realloc(p,arg1) si la un momenta dat am nevoie de marimea de memorie ocupata de p ?

operator *, la pointeri cum se numeste? * - adresa?, adica *p - adresa catre p, iar p pointer?

ca nu inteleg cand atribuim
*p = 3; (compilatorul scrie in adresa lui p, 3)
iar cand p = 0x1, schimba adresa lui p? acolo unde am scris mai devreme 3, cine sterge ?

si nu mai inteleg de ce in cazul de mai jos primesc segmentation fault ?

  p = (int*) 0xA;

	*p=2;

	printf("%d\n",*p);

Edited by webulxpert, 01 July 2010 - 23:55.


#32
m3th0dman

m3th0dman

    Senior Member

  • Grup: Senior Members
  • Posts: 9,269
  • Înscris: 03.01.2007

View Postwebulxpert, on 1st July 2010, 19:56, said:

dar cum pot afla cata memorie a fost rezervata pentru un pointer?

adica:

int *x = (int*) malloc(10*sizeof(int));

malloc a rezervat 40 Byte pentru *x.

sizeof(x) returneaza 4.

si de ce cand initializam *x cu o adresa trebuie adresa sa o convertim sa fie de acelas tip ca *x , (int*) malloc(10); ?
Cum ai făcut tu, cu sizeof.
malloc a rezervat 4 bytes pentru *x, 4 bytes pentru *(x+1), 4 bytes pentru *(x+2), etc. 40 în total.

E chiar greșit/nerecomandat să faci cast, dacă folosești un compilator standard de C.


View Postwebulxpert, on 1st July 2010, 19:56, said:

 int *p = (int*) 0x000A;
	printf("val = %d\n",p);
	p = (int*) 1;
	printf("val = %d\n",p);
	printf("size = %d\n",sizeof(p));

out:
val = 11
val = 1
size = 4

cum prima data p are valoare 11 daca are doar adresa atribuita? (atiu ca A in hex = 11).
de ce este necesar sa pun (int*) la p = 1? (int*) converteste in adresa pentru int ? de ce trebuie ?
Habar n-am cum de are 11. Normal ar trebui să aibă 10.

Nu trebuie. Eu unul nu înțeleg ce vrei să faci.


View Postwebulxpert, on 1st July 2010, 19:56, said:

primesc eroare cand execut codul:

  int i=0;
	char *c = (char*)malloc(sizeof(char));
	ifstream myfile;
	myfile.open("fisier.txt");

	while( ! myfile.eof())
	{
		i++;
		c[i] = myfile.get();
		c = (char*) realloc(c,(i+1)*sizeof(char));
	}

	for(int j=0; j<i; j++)
	{
		printf("%s",c[j]);
	}
L-ai compilat în C sau C++? La o primă vedere ai la printf ai dat %s și c[j] adică îi spui să-ți tipărească tot stringul și-i dai doar un element al său.


View Postwebulxpert, on 1st July 2010, 20:51, said:

daca fac printf("%d",*p) primesc segmentation fault.
Unde apelezi funcția respectivă?

View Postwebulxpert, on 1st July 2010, 20:51, said:

daca am inteles corect:

*p = aici atribuit adresa
p = atribui valoare care se retine in adresa
&p - este adresalui *p

da?
Nu, la toate 3.
*p-reprezintă valoarea spre care pointează p, nici o adresă
p-reprezintă valoarea lui p, adică adresa la care este stocată *p,
&p-reprezinta adresa lui p, nu adresa lui *p; adresa lui *p este în p
Tu de fapt ce-ai citit despre pointeri?

View Postwebulxpert, on 1st July 2010, 20:51, said:

cu int *c = (int*) malloc(10*4);

daca vreau sa atrbui o valoare pentru primii 4 biti lui c,

fac
c = (int*) val (pentru ce trebuie (int*)? [la malloc am inteles pentru ce]).
urmatorii 4 biti sunt
c[1]
sau
c+1 ?

daca vreau sa atribui pentru urmatorii 4 biti cum fac?
Deja ai atribuit o valoare pentru primii 4 biți ai lui c (de fapt unicii biți ai lui c) când ai dat malloc.
Următorii 4 biți sunt c+1 și ei sunt atribuiți din moment ce în malloc ai alocat 40 de biți. Tu n-ai alocat 40 de biți pentru c și 0 pentru c+1, c și c+1 fiecare având 4 biți (deoarece sunt int).
Dar acestea sunt adresele.
Dacă vrei să atribui valori utile, adică în adresa stocată să pui ceva util scrii
*c=24;
*(c+1)=35;/*sau c[i]=35 sau i[c]=35; c[i] e de fapt *(c+i)=*(i+c)=i[c] nu-i mare chestie, e doar comutativitatea adunării care se aplică și în aritmetica pointerilor în C.*/

View Postwebulxpert, on 2nd July 2010, 00:53, said:

nu am prea inteles cum aflu cata memorie a fost rezervata pentru un pointer, adica folosec realloc(p,arg1) si la un momenta dat am nevoie de marimea de memorie ocupata de p ?


operator *, la pointeri cum se numeste? * - adresa?, adica *p - adresa catre p, iar p pointer?


ca nu inteleg cand atribuim
*p = 3; (compilatorul scrie in adresa lui p, 3)
iar cand p = 0x1, schimba adresa lui p? acolo unde am scris mai devreme 3, cine sterge ?


si nu mai inteleg de ce in cazul de mai jos primesc segmentation fault ?
  p = (int*) 0xA;

	*p=2;

	printf("%d\n",*p);
Cu sizeof. Realloc face altceva. Dă exemplu concret ce și cum.

Se numește operatorul de derefernțiere (dereferecnce operator). Operatorul de referențiere (sau address-of) este &.

Nu. Când dai *p=3 scrie 3 în adresa memorată în valoarea lui p. Da, când scrii p=(int*) 0xA, schimbă adresa lui p, ceea ce este aiurea că tu n-ai de unde ști ce-i la 0xA, să poți face ce vrei tu cu ea. Va șterege cine are nevoie de memoria respectivă.

Că tu încerci să bagi 2 într-un loc în care este altceva. Adică tu îl pui pe p să pointeze spre o zonă de memorie unde cu siguranță se află ceva util (adică spre 0xA) și acolo îl obligi să scrie 2. Tu n-ai de unde ști care memorie este liberă să poți da direct valoare lui p; de aia există funcția malloc.
Corect e
int *p;
p=malloc(sizeof(int));//acum p pointează spre o zonă de memorie în care tu poți face ce vrei
*p=2;
Am scris și mai sus, dar deageaba.

Edited by m3th0dman, 02 July 2010 - 00:55.


#33
gnomemory

gnomemory

    Junior Member

  • Grup: Members
  • Posts: 59
  • Înscris: 12.12.2007
@webulexpert
 p = (int*) 0xA;

	*p=2;

	printf("%d\n",*p);

Singurele zone de memorie la care ai tu acces sunt acelea ale variabilelor care se gasesc la un moment dat pe stack, si cele alocate prin malloc / realloc (practic de heap allocator).

In exemplul tau de cod ai ales o adresa la intamplare si te astepti sa ii modifici valoarea. In schimb adresa aceea nu iti apartine, nu ti-a fost anterior alocata (nici de heap allocator, si nu ii corespunde unei variabile de pe stack).

Quote

am impresia ca daca folosim:
*p = 2;
*(p+1) = 3;

ar trebui sa folosim si
*p[2] = 4;

Ti-am mai explicat *(p+n) e echivalent cu p[n] . Nu am facut eu sintaxa.
Dupa regula expusa mai sus *p[2] ar putea fi echivalent in schimb cu **(p+2) adica un fel de p[2][0] .

Quote

ca nu inteleg cand atribuim
*p = 3; (compilatorul scrie in adresa lui p, 3)
iar cand p = 0x1, schimba adresa lui p? acolo unde am scris mai devreme 3, cine sterge ?
Regula e foarte simpla. Cine aloca sterge. Daca e pe stack, nu trebuie sa dai free, ca nu gestionezi tu regiunea asta. Daca e pe heap, tu esti insarcinat cu de-alocarea resurselor.
Pentru fiecare malloc/calloc trebuie sa existe un free pereche.
De exemplu:
#include <stdio.h>
#include <stdlib.h>

#define N 100

int main()
{
	int i;
	int **p;
	p = malloc(sizeof(*p)*N);

	for(i=0; i<N; ++i) {
		int y = i; /* Pentru y se ocupa stack-ul cu dealocarea */
		p[i] = malloc(sizeof(**p)); /* Aici tu ai alocat, tu vei da free */
		*p[i] = i;
	}

	/* Ai facut 101 de alocari anterioare */
	for(i=0; i<N; ++i){
		printf("%d ", *p[i]);
		free(p[i]); /* 100 de dealocari */
	}
	free(p); /* Inca o dealocare */

	return (0);
}


#34
webulxpert

webulxpert

    Senior Member

  • Grup: Senior Members
  • Posts: 2,065
  • Înscris: 28.09.2006
daca am inteles corect, pentru int **p trebuie sa fac dealocarea:


void destroy(int** m)
{
	for(int i=0; i<10; i++)
	{
		for(int j=0; j<10; j++)
		{
			free((m+i)+j);
		}
		free((m+i));

	}

	free(m);

}

iar daca am
  int **m = (int**) malloc(sizeof(*m)*10);

si pentru fiecare *(*(m+i)+j) am alocat memorie, cu ce parametru trebuie sa apelez functia destroy?

#35
gnomemory

gnomemory

    Junior Member

  • Grup: Members
  • Posts: 59
  • Înscris: 12.12.2007
Daca ai:
int **p = (int**) malloc(sizeof(*p)*10);

Tu ai alocat memorie pentru 10 pointeri.
Ai facut o singura data malloc, deci trebuie sa faci o singura data free.

Daca in plus ai alocat memorie pentru fiecare din cei zece pointeri:
for(int i = 0; i < 10; ++i){
	p[i] = (int*) malloc(sizeof(**p));
}

Trebuie sa faci 10 free-uri suplimentare:
for(int i = 0; i < 10; ++i){
	free(p[i]); /* Sau free(*(p+i)); */
/* Free-urile corespunzatoare fiecarei alocari in parte pentru 
pointerii alocati in codul de mai sus */
}
free(p); /* Free-ul corespunzator primului malloc */

Daca ai o semnatura de forma asta:
void destroy(int **p);
Parametrul care trebuie sa-l dai este chiar p.

PS: Daca ai Linux, pentru a vedea daca nu cumva ai memory leak-uri in codul tau, foloseste valgrind.
Daca ai Ubuntu/Debian:
sudo apt-get install valgrind
Daca ai Fedora:
yum install valgrind
Ruleaza apoi:
 valgrind ./binarul_tau
Si sa o vezi daca numarul de free-uri e corespunzator cu numarul de alocari.

#36
webulxpert

webulxpert

    Senior Member

  • Grup: Senior Members
  • Posts: 2,065
  • Înscris: 28.09.2006
am codul:

void destroy(int** m)
{
	for(int i=0; i<10; i++)
	{
		for(int j=0; j<10; j++)
		{
			free((m+i)+j);
		}
		free((m+i));

	}

	free(m);

}


int main ()
{
	int *v = (int*) malloc(sizeof(*v)*10);
	int **m = (int**) malloc(sizeof(*m)*10);

	for (int i=0; i<10; i++)
	{
		*(m+i) = (int*) malloc(sizeof(int)*10);
	}

	for (int i=0; i<10; i++)
	{
		for (int j=0; j<10; j++)
		{
			*(*(m+i)+j) = i;
		}
	}

	for (int i=0; i<10; i++)
	{
		for (int j=0; j<10; j++)
		{
			printf(" %d ",m[i][j]);
		}

		printf("\n");
	}

	destroy(m);

}

primesc eroarea:

Attached Files

  • Attached File  er.png   10.77K   68 downloads


Anunturi

Bun venit pe Forumul Softpedia!

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

Forumul Softpedia foloseste "cookies" pentru a imbunatati experienta utilizatorilor Accept
Pentru detalii si optiuni legate de cookies si datele personale, consultati Politica de utilizare cookies si Politica de confidentialitate