Prima di cominciare, dovresti provare a scrivere un codice corretto che non sollevi avvisi prima di cercare di capire cosa succede sotto il cofano e perché alcune espressioni errate danno ancora risultati corretti.
C è un linguaggio molto permissivo, cioè finché il compilatore è in grado di tradurre ciò che legge presuppone generalmente che il programmatore sappia perché l'ha scritto. È quello che succede qui.
In C, l'indirizzo di un struct
può essere inoltrato a un indirizzo al suo primo elemento. Quindi (void *) &curr
corrisponde a (void *) &(curr->val)
. Qui lancio tutto a void *
per assicurarmi di avere tipi di puntatori compatibili.
Ciò significa che *((int *) curr)
è un'espressione C perfettamente definita e il suo valore è effettivamente curr->val
. Ma è corretto, perché ho scritto un cast puntatore esplicito.
Cosa hai scritto funziona solo per errore, perché come curr
è un tipo aggregato; si passa un int
ed un item *
-printf
e utilizzare solo il suo primo valore - questo è non è più di serie C e posso solo supporre un classico implementazione intuire che. Ma basta sostituire i comandi di stampa dal che:
printf("%d - %d\n", curr->val, 12);
printf("%d - %d\n", *curr, 15);
Si dovrebbe vedere spazzatura nel secondo printf
, perché con %d
si dichiara che si passa un semplice int
ed effettivamente passare un aggregato. Anche in questo caso, nulla è esplicitamente richiesto per standard, ma un'implementazione comune dovrebbe dare questo risultato.
TL; DR: Come *curr
non è un int
, printf("%d\n", *curr);
è un comportamento indefinito. Ciò significa che tutto può accadere, anche il risultato atteso, ma una versione diversa dello stesso compilatore, o un altro compilatore, o anche un cambiamento nei parametri di compilazione potrebbe dare un risultato diverso, così come un piccolo cambiamento nel codice.
E C consente il cast automatico di puntatore ae da void *
e non si dovrebbe mai trasmettere il valore restituito di malloc
in quanto può nascondere i bug. Si prega di scrivere:
curr = malloc(sizeof(item));
Non è più C++ compatibili, ma è corretto C.
Se si compila con avvisi, la linea "printf (" % d \ n "* curr);" dovrebbe stampare un avviso poiché struct node non è un numero intero. Mentre c'è un motivo per cui si vede questo comportamento, è un po 'complicato e ha a che fare con il modo in cui i vararg vengono gestiti in C. Probabilmente dovresti semplicemente evitare di farlo in modo che il comportamento sia più comprensibile. –
'printf ("% d \ n ", * curr);' è un comportamento indefinito perché '* curr' non è un int. – immibis
In aggiunta a ciò che i commenti precedenti hanno correttamente indicato, per riferimento, l'accesso agli elementi con '(* curr) .val' è uguale a' curr-> val' – wolfsgang