Skocz do zawartości

Witaj!

Zaloguj lub Zarejestruj się aby uzyskać pełny dostęp do forum.

Zdjęcie
- - - - -

Dereferencja wskaznika typu void*


  • Zaloguj się, aby dodać odpowiedź
3 odpowiedzi w tym temacie

#1 macsurf

macsurf
  • 104 postów
  • SkądKołobrzeg

Napisano 20 sierpnia 2014 - 17:33

Jak dokonać dereferencji wskaźnika typu void* ? Ciągle otrzymuję warningi:
warning: initialization makes pointer from integer without a cast
Chcę odczytać adres zaalokowanej pamięci, który jest przechowywany we wskaźniku typu void* userdata

char* data = *(char*)userdata;

Co zrobić ? Jak widać po komunikacie on przypisuje inta do zmiennej typu char* która jest 8bajtowa, więć przypisuje tylko ostatnie 4 bajty z wyłuskanego wskaźnika userdata :/
Mam bawić się w operacje bitowe ? czy istnieje jakiś cywilizowany sposób aby pobrać pełny adres po dereferencji tego wskaźnika ?

#2 macsurf

macsurf
  • 104 postów
  • SkądKołobrzeg

Napisano 20 sierpnia 2014 - 21:55

Przekopałem cały internet i zero :/ Więc zacząłem kombinować, jakby to nielogicznie wyglądało to zapis powinien być taki:

char* data = *(char**)userdata;

Zmienna userdata to adres zmiennej wskaźnikowej typu void, która zawiera w sobie adres pamięci zaalokowanej malloc(). Z uwagi, iż do funkcji był przekazywany adres samej zmiennej jako argument userdata a nie adres zaalokowanej pamięci ( to na co wskazywała - jej wartosc ) - tak aby później zrobić realloc ( przeadresowanie na inny blok pamieci - zmiana adresu ) to przez takie podejście trzeba było w ten dziwny sposób rzutować zmienna wskażnikową aby wyłuskać właściwy adres zaalokowanej pamięci :/ Bez tego realokacja w samej funkcji nie miała by sensu gdyż po zakończeniu funkcji nowy adres spowodowałby wyciek pamięci - brak przypisania do adresu pamieci na który wskazywała zmienna poza funkcją.

#3 Tojot

Tojot
  • 1 187 postów

Napisano 20 sierpnia 2014 - 23:17

Trzeba było wkleić trochę więcej kodu, bo to co napisałeś słowami jest wewnętrznie sprzeczne.

#4 macsurf

macsurf
  • 104 postów
  • SkądKołobrzeg

Napisano 21 sierpnia 2014 - 10:47

Może nie tyle sprzeczne co zagmatwany opis.
Mój błąd bo faktycznie przy wyłuskiwaniu adresu trzeba było zrzutować wskaznik na typ (char**) a nie (char*).
Jakby nie patrzeć w funkcji był przekazywany adres zmiennej wskaźnikowej typu void, która zawierała adres zaalokowanego bloku pamięci, więc jakby nie patrzeć wyłuskując taki adres to mamy do czynienia ze wskaźnikiem do wskaźnika.

A kod wygląda tak:


char* data = (char *)malloc(sizeof(char) * 1);
CURL* curl;

/.../
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &writeCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);     // tutaj z uwagi na realokacje pamieci trzeba bylo wyslac adres zmiennej wskaznikowej


// funkcja dla curla
size_t writeCallback(char* buffer, size_t size, size_t nmemb, void* userdata)
{

	char* data = *(char**)userdata;				// wskaznik na dane - wyluskanie wskaznika z przekazanego adresu zmiennej zewnetrznej
	void *tmp;							// tymczasowy wskaznik dla realokowania pamieci
	size_t realsize = size * nmemb;			// ilosc pobranych danych przez writeCallback
	int i = 0;								// licznik dla petli pobierajacej dane z bufora
	static int totalsize = 0;					// suma pobranych danych


	totalsize += realsize + 1;


	if( (tmp = realloc(data, totalsize * sizeof(char))) == NULL)
	{
		printf("blad podczas realokacji pamieci \n");
		return realsize;
	}
	else
	{
		
		*(char**)userdata = tmp;				// ustawienie adresu nowo zaalokowanego obszaru pamieci
		data = (char *)tmp;
		memset(data + (totalsize - realsize), 0, realsize);
	}
	

	for(i = 0; i < realsize; ++i)
	{
		*(data + length + i) = *(buffer + i);
	}

	return realsize;
}





Użytkownicy przeglądający ten temat: 1

0 użytkowników, 1 gości, 0 anonimowych