Wynikiem b - a
określa się tylko wówczas, gdy obie a
i b
wskazują elementy o tej samej tablicy char. To wymaganie może być również interpretowane jako a
i b
wskazujące na bajt należący do tego samego obiektu, ponieważ każdy obiekt może zostać ponownie zinterpretowany jako tablica znaków.
W przeciwnym razie wynik jest niezdefiniowany. To znaczy. próba odjęcia takich wskaźników skutkuje niezdefiniowanym zachowaniem.
Po zdefiniowaniu wyniku ma on typ ptrdiff_t
. ptrdiff_t
to nazwa typedef i ukryty za tą nazwą typedef jest zdefiniowany przez implementację. Typ jest znany z tego, że jest podpisany.
Należy również zauważyć, że język C nie gwarantuje, że ptrdiff_t
jest wystarczająco duży, aby pomieścić wynik jakiegokolwiek odejmowania, nawet jeśli wskaźniki wskazują elementy tej samej tablicy. Jeśli wskaźniki są zbyt oddalone od siebie, aby typ ptrdiff_t
mógł pomieścić wynik, zachowanie jest niezdefiniowane.
Nie ma specyficzny specifier Format printf
dla ptrdiff_t
nawet w C99, więc prawdopodobnie będziesz lepiej przekształcenie go do wystarczająco dużej podpisanej typu całkowitego i użyć formatu specyfikatora dla tego typu
printf("%ld\n", (long) (b - a));
Correction : C99 ma modyfikator długości dla ptrdiff_t
. Właściwym sposobem, aby wydrukować wynik w C99 byłoby
printf("%td\n", b - a);
Zauważ, że t
jest modyfikator długości. Można go łączyć ze specyfikacjami konwersji d
, o
, u
, x
lub X
, w zależności od tego, jaki format wyjściowy chcesz uzyskać. W C89/90 nadal będziesz musiał trzymać się za pomocą odpowiednio dużego podpisanego typu.
P.S. Powiedziałeś, że nie możesz sobie wyobrazić, że zawodzi na maszynie 32-bitowej lub 64-bitowej. W rzeczywistości bardzo łatwo jest sobie wyobrazić (lub faktycznie to zrobić) porażkę. Zobaczysz, że ptrdiff_t
na komputerze 32-bitowym jest zwykle typu 32-bitowego. Ponieważ jest to typ podpisany, ma tylko 31 bitów dostępnych do reprezentowania wielkości wartości. Jeśli weźmiesz dwa wskaźniki, które są dalej od siebie (tj. Wymagają 32 bitów do reprezentowania "odległości"), wynik b - a
przepełni się i będzie pozbawiony znaczenia.Aby zapobiec tej usterce, potrzebujesz co najmniej 33-bitowego podpisu ptrdiff_t
na 32-bitowym komputerze i co najmniej 65-bitowego podpisu ptrdiff_t
na maszynie 64-bitowej. Implementacje zwykle tego nie robią, po prostu używają "uprawnienia" standardu do tworzenia niezdefiniowanych zachowań w przepełnieniu.
+1 Dla C typowych dziwactw, takich jak różnica wskaźnika nie pasująca do wnętrza 'ptrdiff_t' (mogę też wymyślić dużo obrzydliwsze słowa niż" dziwactwa "). –
Tak, okazuje się, że 'PTRDIFF_MIN' /' PTRDIFF_MAX' może być tak mały jak +/- 65536 (zgodnie ze specyfikacją). Sprawdzone przeze mnie implementacje nie zrobiły jednak takich szalonych rzeczy - w praktyce wydaje się mało prawdopodobne, że coś dziwnego się pojawi. –
Rozważałbym implementację, w której 'ptrdiff_t' jest mniejszy (szerokość w bitach) niż największy możliwy rozmiar tablicy, który jest nie do złamania, a nawet implementacje, w których liczba bitów * wartości * jest mniejsza (np. Tablice większe niż elementy' SIZE_MAX/2' dozwolone) raczej niebezpieczne ... –