Jaka jest różnica w używaniu\% p,\% u i\% x do drukowania zmiennych adresów w C?


Najlepsza odpowiedź

Jeśli chcesz wydrukować adres lub zawartość zmiennej wskaźnikowej, jedynym prawdziwie przenośnym sposobem na to jest użycie specyfikatora formatu\% p. Standard C stwierdza, że ​​drukowane znaki są zdefiniowane przez implementację, ale w praktyce większość implementacji bibliotek C generuje sekwencję cyfr szesnastkowych reprezentujących adres.

Specyfikatory formatu\% u i\% x oczekują liczby całkowitej bez znaku i wydrukuj wartość odpowiednio w systemie dziesiętnym i szesnastkowym. Nie oczekują adresu .

Jeśli użyjesz\% u lub\% x (lub czegokolwiek innego niż\% p), aby spróbować wydrukować adres, może wydawać się działać w niektórych środowiskach, ale w rzeczywistości będzie niezdefiniowane zachowanie i nieprzenośne . Nie można założyć, że rozmiar wskaźnika jest taki sam, jak rozmiar liczby całkowitej bez znaku (lub dowolnego innego typu danych typu integer). Na przykład w wielu środowiskach 64-bitowych liczba całkowita bez znaku ma 32 bity. Jeśli liczba bitów we wskaźniku nie zgadza się z liczbą bitów w liczbie całkowitej bez znaku w twoim środowisku i spróbujesz użyć\% u lub\% x do wydrukowania adresu, otrzymasz nieprawidłowe dane wyjściowe, a wynik kolejnych elementy w tym samym wywołaniu printf również mogą być niepoprawne.

Tak więc, jeśli zamierzasz wydrukować adres, zawsze używaj specyfikatora formatu\% p dla przenośnego kodu, który unika niezdefiniowanego zachowania. Nigdy nie zakładaj, że rozmiar wskaźnika jest taki sam, jak rozmiar dowolnego innego typu danych C.

Odpowiedź

Tylko \%p konwersja poprawnie rozumie wskaźnik. Konwersja \%p drukuje wskaźnik w sposób specyficzny dla implementacji.

\%u i są przeznaczone dla typów unsigned int lub int, które mogą mieć taki sam rozmiar jak typ wskaźnika lub nie. Konwersja \%u wypisuje liczbę całkowitą dziesiętną bez znaku, podczas gdy \%x wypisuje liczbę szesnastkową bez znaku małymi literami.

Aby wydrukuj wskaźnik za pomocą \%u lub \%x, będziesz musiał rzucić wskaźnik na int lub unsigned int. Rzutowanie może utracić informacje, jeśli sizeof(void *) > sizeof(int).

Zobacz też: printf, fprintf, sprintf, snprintf, printf\_s , fprintf\_s

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *