Wskaźniki nie są liczbami całkowitymi ze znakiem, a są bardziej podobne do liczb całkowitych bez znaku. Jednak drukujesz je tak, jakby były liczbami całkowitymi ze znakiem. W systemie 32-bitowym istnieje kilka rzeczy, które mogą mieć długość 32 bitów: int
, , float
oraz wskaźniki. Zasadniczo nie można powiedzieć, które z nich są po prostu patrząc na nie, ale wszystkie one oznaczają różne rzeczy. (W trakcie eksperymentu możesz przekazywać różne liczby całkowite i drukować je jako pływające i odwrotnie: ogólnie jest to zła praktyka, ale może pokazać, że różne typy danych oznaczają różne rzeczy.)
Funkcje, które przyjmują liczbę zmienną Argumenty (funkcje "variadic") robią to w skomplikowany sposób. W szczególności nie sprawdzają typów argumentów. Możesz przekazywać dowolne argumenty, które lubisz, do printf()
i podobnych funkcji, ale Twoim problemem jest uzgodnienie ich ze specyfikatorem formatu. Oznacza to, że funkcja nie ma żadnego sposobu na uzyskanie prawidłowego typu (tak, jak gdybyś przekazał float
do funkcji takiej jak int foo(int)
).
Podawanie niewłaściwych typów argumentów prowadzi do niezdefiniowanego zachowania, a szczególnie może prowadzić do problemów w przypadku przekazania argumentów o niewłaściwym rozmiarze. W większości systemów 64-bitowych wskaźniki to 64-bitowe wartości, a int
s to 32.
Dlatego należy użyć właściwej rzeczy w ciągu formatującym. printf("%p", &a);
wydrukuje adres a
jako wskaźnik, który jest tym, czego potrzebujesz. Standard wymaga czegoś takiego jak printf("%p", (void *)&a);
, ale w praktyce jest to niepotrzebne na każdym komputerze, z którym możesz się kiedykolwiek zetknąć.
'% 08x' nie jest przenośny (i faktycznie być pomieszane na platformie LLP64, na przykład) . –
Tak, dlatego powinieneś użyć '% p', ale nadal warto wspomnieć, że wiele osób używa'% 08x' na 32-bitowych komputerach. 99% czasu, jeśli drukujesz wartość wskaźnika, debugujesz coś, dzięki czemu wiesz dokładnie, jakiej architektury używasz. –