Na forum 4programmers.net korzystamy z plików cookies. Część z nich jest niezbędna do funkcjonowania
naszego forum, natomiast wykorzystanie pozostałych zależy od Twojej dobrowolnej zgody, którą możesz
wyrazić poniżej. Klikając „Zaakceptuj Wszystkie” zgadzasz się na wykorzystywanie przez nas plików cookies
analitycznych oraz reklamowych, jeżeli nie chcesz udzielić nam swojej zgody kliknij „Tylko niezbędne”.
Możesz także wyrazić swoją zgodę odrębnie dla plików cookies analitycznych lub reklamowych. W tym celu
ustaw odpowiednio pola wyboru i kliknij „Zaakceptuj Zaznaczone”. Więcej informacji o technologii cookie
znajduje się w naszej polityce prywatności.
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.
Usunąć wpis?
Tej operacji nie będzie można cofnąć.
qwertyuiop
qwertyuiop
0
Jakby nie patrzeć, to tablica 4-elementowa typu char ma taką samą wielkość jak int, więc można zrobić tak:
Kopiuj
unsignedchar data[4];unsignedint t;
data[0]=144;
data[1]=24;
data[2]=0;
data[3]=0;
t =*((unsignedint*)data);
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ć?
operator >> traktuje białe znaki jak jako separator, który należy ignorować. użyj input.get(read);
Usunąć wpis?
Tej operacji nie będzie można cofnąć.
stary_przyjacie_z_wi
stary_przyjacie_z_wi
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
unsignedchar data[4];unsignedint t =6288;
data =((unsignedchar*)t);
char data[4];unsignedint 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.
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.
Usunąć wpis?
Tej operacji nie będzie można cofnąć.
stary_przyjacie_z_wi
stary_przyjacie_z_wi
0
Wiem, tylko chodziło mi o to czy jednak nie ma jakiegoś uniwersalnego sposobu, że np jakiś reinterpret_cast załatwi wszystko.
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.
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.
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.
Usunąć wpis?
Tej operacji nie będzie można cofnąć.
stary_przyjacie_z_wi
stary_przyjacie_z_wi
0
Tutaj funkcja wraz z innymi używanymi w niej:
Kopiuj
voidstworz_tablice(unsignedchar*&temp,constunsignedint rozmiar){
temp =newunsignedchar[rozmiar];for(unsignedint i =0; i < rozmiar; i++)
temp[i]=0;}voidzeruj(constunsignedchar*temp){
temp =0;}voidzeruj(constunsignedint*temp){
temp =0;}voidusun(constunsignedchar*temp){delete[]temp;zeruj(temp);}voidprzenies_liczbe(constunsignedint liczba,unsignedchar*&data,unsignedint&start,constunsignedint rozmiar){unsignedchar*konwersja =0;stworz_tablice(konwersja, rozmiar);unsignedint*wynik =reinterpret_cast<unsignedint*>(konwersja);*wynik = liczba;for(unsignedint 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.
Usunąć wpis?
Tej operacji nie będzie można cofnąć.
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.