Nie.
„Typ danych” zmiennej ma znaczenie tylko w kodzie źródłowym (a nawet tylko w niektórych językach). Mówi kompilatorowi, jak traktować zmienną.
Te typy danych wysokiego poziomu nie istnieją jako takie w skompilowanym (natywnym) kodzie. Mogą wpływać na to, jakie instrukcje generuje kompilator, ale same instrukcje nie dbają o to, czy dane reprezentują znak, czy liczbę.
Zmienne nie istnieją w sprzęcie. W sprzęcie masz lokalizacje pamięci i instrukcje, które na nich działają.
Zmienna może być postrzegana jako widok danych w miejscu pamięci - jeśli spojrzysz na tę samą pamięć nieco inaczej (inna zmienna różnego typu odnosząca się do tej samej lokalizacji), ta sama wartość binarna może mieć inne znaczenie .
Na przykład bajt 0x41 może być interpretowany jako znak zakodowany w UTF-8 A
. Można to również interpretować jako liczbę całkowitą jednobajtową 65
. Może być również interpretowany jako jeden bajt w wielobajtowej liczbie całkowitej lub liczbie zmiennoprzecinkowej, lub jeden bajt w wielobajtowym kodowaniu znaków. To może być bitset 0b1000001
. Wszystkie z tego samego bajtu w tej samej lokalizacji w pamięci. W języku C można zobaczyć ten efekt, rzutując na te różne typy.
Kiedy masz „przepełnienie bufora”, robisz coś poza granicami tego, czego może oczekiwać Twój kompilator lub język. Ale jeśli chodzi o sprzęt 1 , zapisujesz bajty (pojedyncze lub wielokrotne) w miejscu w pamięci. Lokalizacja pamięci nie ma „typu”. W rzeczywistości sprzęt nie wie nawet, że określony zestaw bajtów tworzy tablicę lub bufor w kodzie.
Ilekroć następnym razem uzyskasz dostęp do tej lokalizacji pamięci w kodzie, instrukcje będą działać zgodnie z pierwotną definicją. np. jeśli spodziewali się tam liczby, będą działać na dowolnych bajtach danych, tak jakby byli liczbą.
Na przykład, zakładając, że int
jest to 4-bajtowa (32-bitowa) liczba całkowita ze znakiem:
+-------------+--------------------------------------------+-----------+
| Source code | char[15] | int |
+-------------+--------------------------------------------------------+
| Memory |61|61|61|62|62|62|63|63|63|64|64|64|65|65|65|EF|BE|AD|DE|
+-------------+--------------------------------------------------------+
Widać int
teraz 0xEFBEADDE
, że lokalizacja pamięci zawiera teraz , zakładając, że system big-endian 2 . To jest podpisany 32-bitowy int -272716322
. Teraz, jeśli interpretujesz tę samą pamięć jako int bez znaku int ( uint
), byłoby to 4022250974
zamiast tego. Dla dokładnie tych samych danych w pamięci znaczenie zależy całkowicie od tego, jak je przeglądasz.
1 Istnieją pewne mechanizmy, które uniemożliwiają zapisywanie w chronionych obszarach pamięci i powodują awarię programu, jeśli spróbujesz to zrobić.
2 x86 jest właściwie little-endianem, co oznacza, że interpretujesz bajty składające się na większą wartość wstecz. Tak więc na x86 miałbyś zamiast tego 0xDEADBEEF
dać podpisany -559038737
lub niepodpisany 3735928559
.