Δημοσιεύτηκε: 09 Σεπ 2011, 09:47
Και τώρα μερικές χρήσιμες σημειώσεις,. σχετικές με τα παραπάνω...
Καταρχήν οι διευθύνσεις μνήμης είναι πάντα unsigned. Στις αρχές ήταν unsigned int ( %u) ... πλέον είναι unsigned long int ή και unsigned long long int ( %llu ), ανάλογα την πλατφόρμα και τον compiler. Σίγουρα πάντως ΔΕΝ είναι int ( %d ).
Από την αναθεώρηση C99 και μετά, το casting από δείκτες σε int, long int και long long int (unsigned ή μη) έχει σταματήσει να θεωρείται συμβατό ανάμεσα στους compiler, μιας και ορίστηκε ως "implementation dependent" που σημαίνει πως σε ορισμένους compilers μπορεί να δίνει ακόμα και undefined αποτέλεσμα (δηλαδή τυχαίο, που δεν αντιστοιχεί στη πραγματική διεύθυνση μνήμης).
Σε ότι αφορά τώρα τη χρήση του %p για το τύπωμα διευθύνσεων μνήμης, νομίζω δεν ανήκει στα στάνταρ της γλώσσας αλλά δεν είμαι σίγουρος! Γι αυτό που είμαι σίγουρος είναι πως όποιος compiler το υποστηρίζει περιμένει να του δώσουμε δείκτη τύπου void, άρα οτιδήποτε θέλουμε να τυπώσουμε μέσω του %p πρέπει να το κάνουμε cast σε: (void *)
Δηλαδή το παραπάνω πρόγραμμα, θα γινόταν...
και με %p τα αποτελέσματα βγαίνουν πάντα σε 16αδική μορφή (ενώ με %u, %lu, %llu βγαίνουν σε 10δική μορφή).
Με την υπόθεση πως το %p δεν είναι στάνταρ, ο συμβατός τρόπος για μετατροπές δεικτών σε απρόσημες ακέραιες τιμές προϋποθέτει τη χρήση unions ή struct. Με την ευκαιρία σκέφτομαι να σας πω λίγο για unions (να κάνουμε κι ένα διάλειμμα από τα strings) και να σας δείξω πως μπορούμε να τα χρησιμοποιήσουμε για τις διευθύνσεις μνήμης.
Θα επανέλθω σε καμιά ωρίτσα όμως.
Καταρχήν οι διευθύνσεις μνήμης είναι πάντα unsigned. Στις αρχές ήταν unsigned int ( %u) ... πλέον είναι unsigned long int ή και unsigned long long int ( %llu ), ανάλογα την πλατφόρμα και τον compiler. Σίγουρα πάντως ΔΕΝ είναι int ( %d ).
Από την αναθεώρηση C99 και μετά, το casting από δείκτες σε int, long int και long long int (unsigned ή μη) έχει σταματήσει να θεωρείται συμβατό ανάμεσα στους compiler, μιας και ορίστηκε ως "implementation dependent" που σημαίνει πως σε ορισμένους compilers μπορεί να δίνει ακόμα και undefined αποτέλεσμα (δηλαδή τυχαίο, που δεν αντιστοιχεί στη πραγματική διεύθυνση μνήμης).
Σε ότι αφορά τώρα τη χρήση του %p για το τύπωμα διευθύνσεων μνήμης, νομίζω δεν ανήκει στα στάνταρ της γλώσσας αλλά δεν είμαι σίγουρος! Γι αυτό που είμαι σίγουρος είναι πως όποιος compiler το υποστηρίζει περιμένει να του δώσουμε δείκτη τύπου void, άρα οτιδήποτε θέλουμε να τυπώσουμε μέσω του %p πρέπει να το κάνουμε cast σε: (void *)
Δηλαδή το παραπάνω πρόγραμμα, θα γινόταν...
- Κώδικας: Επιλογή όλων
#include <stdio.h>
int main( void )
{
int n = 10, *p = &n, **paddr = &p;
puts(" int n = 10, *p = &n, **paddr = &p;\n");
printf(" paddr = &p = %p\n", (void *)paddr);
printf(" *paddr = p = %p\n", (void *)*paddr);
printf("**paddr = *p = n = %d\n\n", **paddr);
return 0;
}
και με %p τα αποτελέσματα βγαίνουν πάντα σε 16αδική μορφή (ενώ με %u, %lu, %llu βγαίνουν σε 10δική μορφή).
Με την υπόθεση πως το %p δεν είναι στάνταρ, ο συμβατός τρόπος για μετατροπές δεικτών σε απρόσημες ακέραιες τιμές προϋποθέτει τη χρήση unions ή struct. Με την ευκαιρία σκέφτομαι να σας πω λίγο για unions (να κάνουμε κι ένα διάλειμμα από τα strings) και να σας δείξω πως μπορούμε να τα χρησιμοποιήσουμε για τις διευθύνσεις μνήμης.
Θα επανέλθω σε καμιά ωρίτσα όμως.