Rzutowanie tablicy unsigned char na typ short

Odpowiedz Nowy wątek
2019-05-14 22:18
0

Witam.

Mając taką tablicę:

unsigned char array[] = {1, 0};

Rzutując ją w taki sposób:

short a = *(short*)array;

W a jest wartość 1. Zastanawia mnie dlaczego. Tablica przechowywana jest jako ciągły fragment pamięci. W pamięci najpierw jest wartość 1 jako jeden bajt a potem 0 też jako jeden bajt. Typ short na moim komputerze ma 2 bajty a więc nie powinna być wartość 0x10 ?

edytowany 1x, ostatnio: Sielan, 2019-05-14 22:19

Pozostało 580 znaków

2019-05-14 22:26
2

Poczytaj o endianach... Urok little endianu :) Na innym procesorze miałbyś to, czego się spodziewasz... Dlatego właśnie niewskazane jest proste rzutowanie, jeśli nie wiemy jaką mamy architekturę


Ogólnie na prace domowe mam stawki zaporowe. Czasem coś o programowaniu znajdzie się na mojej stronie

Pozostało 580 znaków

2019-05-14 22:30
0

Wiem, że mam little endian, wiem na czym to polega. Domyślam się, że rzutując to w ten sposób w pamięci najpierw jest umieszczony bajt o wartości 0 a potem o wartości 1 dlatego jako wynik końcowy jest wartość 1 zapisana na 2 bajtach. Tylko nie rozumiem dlaczego skoro kolejność przechowywania bajtów ma znaczenie tylko dla danych o rozmiarze większym niż 1 bajt? Czy elementy tablicy nie są przechowywanie jeden po drugim w takiej kolejności jak zostały zapisanie w tablicy? Jak wyświetlę wartość adresu dla pierwszego elementu tablicy (tam gdzie przechowuję 1) i porównam go do wartości adresu drugiego elementu (tam gdzie 0), to ten pierwszy adres ma mniejszą wartość od 2 więc wygląda na to że te dane nie zostały zapisane w pamięci w little endian.

edytowany 3x, ostatnio: Sielan, 2019-05-14 22:34

Pozostało 580 znaków

2019-05-14 23:10
3

Typ short na moim komputerze ma 2 bajty a więc nie powinna być wartość 0x10 ?

Niby skąd zamiana nibbli? Albo 0x0001 albo 0x0100.

... więc wygląda na to że te dane nie zostały zapisane w pamięci w little endian.

System little/big endian ma wpływ na to jak są zapisywane i odczytywane zmienne kilku-bajtowe.

short tab[]= { 0x0102, 0x0304};
0x01, 0x02, 0x03, 0x04 <- big endian
0x02, 0x01, 0x04, 0x03 <- little endian
0x04, 0x03, 0x02, 0x01 <- oczekujesz tego?
Co by miało zwrócić tab[2]? Wartości sprzed tablicy?

edytowany 3x, ostatnio: Delor, 2019-05-14 23:31

Pozostało 580 znaków

2019-05-15 16:55
kq
1

Ja od siebie dodam, że taki cast to może być UB (a dereferencja po nim jest na pewno) i nie należy go wykonywać. Pomijając już nawet kłopoty z alignmentem.


edytowany 1x, ostatnio: kq, 2019-05-16 08:24
Pokaż pozostałe 3 komentarze
Hm, rzeczywiście. Ciekawe, C explicite zebrania, a C++ explicite zezwala. No cóż, do zapisania do kajecika... Dzięki, TIL. - kq 2019-05-15 23:43
Ciężko mi zrozumieć ten punkt. Z jednej strony faktycznie jest napisane, że wolno konwertować wskaźniki. Z drugiej strony notatka sugeruje, że w szczególności dla uint8_t* x, nie ma gwarancji, że reinterpret_­cast<uint8_t*>(reinterpret_­cast<uint32_t*>(x)) == x. - enedil 2019-05-16 00:13
"Converting a prvalue of type “pointer to T1” to the type “pointer to T2” and back to its original type yields the original pointer value." jest dla mnie dość klarowne - kq 2019-05-16 00:14
Tak, ale w nawiasie jest uwaga o wymogach wyrównania. "the alignment requirements of T2 are no stricter than those of T1" tutaj nie zachodzi, bo wymagania dla uint32_t są większe. - enedil 2019-05-16 00:17
Wygląda na to, że Twoja interpretacja jest poprawna. - kq 2019-05-16 06:48

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0