Funkcja memmove

0

Mam takie pytanie. Kiedyś w delphi korzystałem z funkcji move: Move.

Kopiuj
Move(Data[0],Ver,4);

Funkcja działała na tej zasadzie, że kopiowała 4 kolejne elementy z tablicy Data, typu int do zmiennej Ver, też typu int w taki sposób, że Data[0]=144, Data[1]=24, Data[2]=0, Data[3]=0 i ta funkcja składała to w 6288.

Teraz moje pytanie co do funkcji memmove - czy ona wykona coś takiego? A może znacie jakieś inne sposoby na wykonanie tego? W sumie tamten program robiłem ładny kawał czasu temu i nie mam w ogóle pomysłów.

0

Jakby nie patrzeć, to tablica 4-elementowa typu char ma taką samą wielkość jak int, więc można zrobić tak:

Kopiuj
  unsigned char data[4];
  unsigned int t;
  data[0] = 144;
  data[1] = 24;
  data[2] = 0;
  data[3] = 0;
  t = *((unsigned int *)data);
Xupicor
"Jak by nie patrzeć" to tylko przy założeniu, że int ma 4 bajty - a to nie jest ani gwarantowane, ani zawsze prawdą. ;)
KR
jeszcze się nie spotkałem, żeby w C++ było inaczej.
0

No spoko, a jakby chcieć z określonego przykładu z tej tablicy data?

Wibowit
  • Rejestracja:około 20 lat
  • Ostatnio:około godziny
0

A ręcznie nie możesz poskładać?

t = (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + (data[3]);

Kompilator to automatycznie zoptymalizuje.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
0

Słuchajcie mam jeszcze taki problem. Odczytuję plik binarny do zmiennej typu unsigned char (8 bitów, wartości od 0 do 255) i nie sczytuje mi znaków o kodzie #09, czyli tabulatora. Macie jakiś pomysł jak temu zaradzić?

Funkcja wygląda tak:

Kopiuj
void otworz(istream& input, vector <unsigned int> &data)
{   
    unsigned char read;
	while (input.good())
	{
        input >> read;
        data.push_back(static_cast<int>(read));
	}
}
MarekR22
operator >> traktuje białe znaki jak jako separator, który należy ignorować. użyj input.get(read);
0

Użytkownik qwertyuiop zaproponował pewnie sposób, ciekawi mnie jak zrobić odwrotnie, czyli liczbę typu int wpisać, do 4-elementowej tablicy unsigned char. Próbowałem, ale niestety to nie działa:

Kopiuj
  unsigned char data[4];
  unsigned int t = 6288;
  data = ((unsigned char*)t);
galleanv
a memcpy(...) nie zrobiłoby co trza?
byku_guzio
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 7 lat
0

Jeżeli chcesz kombinować(memcpy powinno dać radę - jak galleanv napisał):

Kopiuj
unsigned char data[4];
unsigned int t = 6288;
unsigned int *w = (unsigned int*)data;
*w = t;

0

To w takim razie jak sobie poradzić z obiema konwersjami używając memcpy?

AR
  • Rejestracja:około 14 lat
  • Ostatnio:około 14 lat
  • Postów:21
0

może tak:

Kopiuj
char data[4];
unsigned int t = 6288;

memcpy( data, &t, 4 );
memcpy( &t, data, sizeof(t) );

Ale i tak trzeba pamietać czy sprzęt jest little endian czy big endian. Dlatego nie wiem czy sposób jaki podał Wibowit nie jest najpoprawniejszy jeśli chodzi o zapis językowy.

edytowany 2x, ostatnio: Arz
0

W sensie, że w big-endian będzie w drugą stronę zapisywał tak?

0

Niestety zarówno wersja byku_guzia jak i Arza powodują błędy pamięci... poniekąd działają...

AR
  • Rejestracja:około 14 lat
  • Ostatnio:około 14 lat
  • Postów:21
0

funkcja memcpy() jest standardową funkcją, a nie moim wymysłem, nie może działać poniekąd. Tylko nie operujesz na typach danych w ten sposób, o czym ostrzegłem. Sposób jaki podał wibowit też w pewnych warunkach nie zadziała. ;) O czym też ostrzegam. Czasem ten problem z konwersją występuje również na innych forach ;) Polecam poczytać o typach danych, o umieszczaniu ich w pamięci. W języku C bez tej wiedzy (z resztą podstawowej) ani rusz.

Chyba nikt tutaj podstaw języka nie będzie przepisywać każdemu z osobna skoro są dostępne w sieci czy księgarni.

0

Wiem, tylko chodziło mi o to czy jednak nie ma jakiegoś uniwersalnego sposobu, że np jakiś reinterpret_cast załatwi wszystko.

quetzalcoatl
  • Rejestracja:ponad 18 lat
  • Ostatnio:ponad 6 lat
0
stary_przyjacie_z_wi napisał(a)

Niestety zarówno wersja byku_guzia jak i Arza powodują błędy pamięci... poniekąd działają...

Nie działają "poniekąd", tylko działają poprawnie, zgodnie z opisanym przez Ciebie zamierzeniem.
Zarówno przykład byku_guzia jak i Arz'a jest poprawny, z tym, że byku_guzio trochę kod zanadto "rozelaborował", pewnie po to, aby było widac co się dokładnie dzieje, a Arz użył memcpy żeby było zwięźlej i żeby nie trzeba było później pisać własnych pętli (np. na przerzucenie bloku kilku intów).

Co rozumiesz poprzez "powodują błędy pamięci"?
W kontekście tych kilku linijek z obu przykładów, to sformułowanie jest kompletnie bez sensu.
Jeśli w swoim programie masz jakies AccessViolation itp to błąd jest u Ciebie, a nie w tych przykładach.
Żadna linia z zamieszczonych przez nich przykładów nie powoduje uszkodzeń/błędów ani na stosie, ani na stercie.

ps. odpowiedz na Twoje ostatnie pytanie:

stary_przyjacie_z_wi napisał(a)

Wiem, tylko chodziło mi o to czy jednak nie ma jakiegoś uniwersalnego sposobu, że np jakiś reinterpret_cast załatwi wszystko.

brzmi:

ps2. czemu w ogole potrzebujesz upychac dane w char[] ?


no to pojechałem z nieobecnością.. chwila przerwy i prawie rok przeleciał
edytowany 2x, ostatnio: quetzalcoatl
0

Ogólnie kompiluje program pod linuxem i co jakiś czas, wraz z nowymi funkcjami, odpalam go z valgrindem, no i on wyrzuca błędy pamięci w tych funkcjach, np. "Invalit write of size 4" właśnie w tej funkcji.

Kiedyś pisałem identyczny program, ale w Delphim, a teraz robię go w C++, chodzi o to, że odczytuje i zapisuje pliki binarne o określonej strukturze wiec wszystkie dane przed zapisem wrzucam do tablicy unsigned char - jeden element ma rozmiar dokładnie 1B, a potem poleceniem nazwapliku.write(tablica_char, ilosc_elementow) zapisuje do pliku binarnego.

quetzalcoatl
  • Rejestracja:ponad 18 lat
  • Ostatnio:ponad 6 lat
0

Musiałbyś pokazać jak to napisałes aby móc sensownie cos odpowiedziec, w kwestii czy robisz to poprawnie..
Generalnie, jest to małoistotne. Piszesz o valgrindzie - jest to narzedzie do analizy bledow obslugi pamieci. W momencie kiedy zaczynasz uzywac funkcji w stylu memcpy albo memmove do robienia sobie wiadomego zamieszania, trudno sie dziwic ze dostajesz jakies informacje/warningi/errory z niego. W ogolnosci, memmove nie sluzy do tego co probujesz zrobic. W ogolnosci, tablice char[] lezace na stosie rowniez nie sluza do takich rzeczy. Acz, mozna je tak wykorzystywac..

Pokaz tę funkcję o która irytuje valgrind'a, ktoś tutaj na pewno będzie w stanie stwierdzic czy wykonuje ona to poprawnie.


no to pojechałem z nieobecnością.. chwila przerwy i prawie rok przeleciał
0

Tutaj funkcja wraz z innymi używanymi w niej:

Kopiuj
void stworz_tablice(unsigned char *&temp, const unsigned int rozmiar)
{
      temp = new unsigned char[rozmiar];   
      for(unsigned int i = 0; i < rozmiar; i++)
           temp[i] = 0;        
}

void zeruj(const unsigned char *temp)
{
     temp = 0;   
}

void zeruj(const unsigned int *temp)
{
     temp = 0;   
}

void usun(const unsigned char *temp)
{
     delete []temp;
     zeruj(temp);    
}

void przenies_liczbe(const unsigned int liczba, unsigned char *&data, unsigned int &start, const unsigned int rozmiar)
{
    unsigned char *konwersja = 0;
    stworz_tablice(konwersja, rozmiar);
    unsigned int *wynik = reinterpret_cast<unsigned int*>(konwersja);
    *wynik = liczba;
    for(unsigned int i = 0; i < rozmiar; i++)
        data[start + i] = konwersja[i]; 
    start += rozmiar;
    usun(konwersja);       
    zeruj(wynik); 
}

Tutaj kod do wywołania:

Kopiuj
 przenies_liczbe(63288, data, offset, 4);

Tablica data to ta docelowa tablica, do której wrzucam, nazwijmy to "po bajcie", to co ma być zapisane do pliku. Przed wrzucaniem do niej danych jest tworzona dynamicznie, nie wiedziałem jak sobie poradzić z tym, że ma być np tylko do 4 elementów tablicy wrzucane więc stworzyłem sobie tablice pomocniczą konwersja i stamtąd kopiuję po kolei do tablicy docelowej.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.