Po pierwsze jako początkujący powinieneś spróbować napisać poprawny kod, który nie ostrzega przed próbą zrozumienia, co dzieje się pod maską i dlaczego niektóre nieprawidłowe wyrażenia wciąż dają poprawne wyniki.
C jest bardzo permisywnym językiem, tak długo, jak kompilator może tłumaczyć to, co czyta, ogólnie zakłada, że programista wie, dlaczego je napisał. To się dzieje tutaj.
W języku C adres struct
można przesłać na adres do pierwszego elementu. Tak więc (void *) &curr
jest taki sam jak (void *) &(curr->val)
. Tutaj rzutuję wszystko na void *
, aby mieć kompatybilne typy wskaźników.
Oznacza to, że *((int *) curr)
jest doskonale zdefiniowanym wyrażeniem C, a jego wartość jest rzeczywiście curr->val
. Ale to prawda, ponieważ napisałem wyraźny rzut wskaźnika.
To, co napisałeś działa tylko przez przypadek, ponieważ jako curr
jest typem złożonym; przekazujesz int
i item *
do printf
i używasz tylko jego pierwszej wartości - to jest już nie standard C i mogę tylko przyjąć klasyczną implementację, aby to odgadnąć. Ale po prostu zastąpić polecenia drukowania przez że:
printf("%d - %d\n", curr->val, 12);
printf("%d - %d\n", *curr, 15);
Powinieneś zobaczyć śmieci w drugim printf
, ponieważ z %d
wyrażają Państwo zdać prosty int
i faktycznie zdać kruszywo. Również tutaj nic nie jest wyraźnie powierzone na standard, ale wspólne wdrożenie powinno dać taki wynik.
TL, DR: jako *curr
nie jest int
, printf("%d\n", *curr);
jest niezdefiniowany zachowanie. Oznacza to, że wszystko może się zdarzyć, nawet oczekiwany wynik, ale inna wersja tego samego kompilatora lub innego kompilatora, a nawet zmiana parametrów kompilacji może dać inny wynik, podobnie jak drobna zmiana w kodzie.
A C pozwala na automatyczny rzut wskaźnika do iz void *
i nigdy nie powinieneś używać wartości zwracanej malloc
, ponieważ może ona ukrywać błędy. Proszę napisać:
curr = malloc(sizeof(item));
To już nie jest C++ zgodne, ale jest to prawidłowe C.
Jeśli kompilujesz z ostrzeżeniami, linia "printf (" % d \ n "* Curr);" powinien wydrukować ostrzeżenie, ponieważ węzeł struct nie jest liczbą całkowitą. Chociaż istnieje powód, dla którego widzisz to zachowanie, jest to nieco skomplikowane i ma związek z obsługą varargs w C. Prawdopodobnie powinieneś po prostu unikać tego, aby zachowanie było bardziej zrozumiałe. –
'printf ("% d \ n ", * curr);' jest niezdefiniowanym zachowaniem, ponieważ '* curr' nie jest int. – immibis
Oprócz tego, co powyższe komentarze poprawnie wskazano, dla odniesienia, dostęp do elementów z '(* curr) .val' jest taki sam jak' curr-> val' – wolfsgang