IN3R11-2 { CCours 3Damien MASSONd.masson@esiee.frhttp://esiee.fr/ massond/Teaching/IN3R11-2/~23 novembre 2010Le retour des pointeurspointeur = adresse memoire + typetype* nom; nom pointe sur une zone memoire correspondantau type donnele type peut ^etre quelconquevaleur speciale NULL equivalente a 0pointeur generique : void* nom;l’operateur & donne l’adresse d’une variable&*t == t puisque de la variable pointee par t... est t#include int main( int argc , char argv [])fint i ;int t = &i ;printf ("%d\n",&t==t) ;/ 1 /g2/22Passage par adressevoid swap(int a, int b) void swap(int a, int b)f fint tmp = a; int tmp = a;a = b; a = b;b = tmp; b = tmp;g gint main( int argc , char argv) int main( int argc , char argv)f fint a = 5,b = 10; int a = 5,b = 10;swapt(a,b) ; swapt(&a,&b) ;printf ("a = %d, b = %d" ,a,b) ; printf ("a = %d, b = %d" ,a,b) ;/ a = 5, b = 10 / / a = 10, b = 5 /g g3/22Arithmetique des pointeursint* t on peut voir t comme un tableau d’int : *t = t[0]l’addition et la soustraction se font en fonction de la taille deselements du tableaudouble t [10];printf ("%d\n" ,t+2==(void)t+2sizeof (double)) ; / 1 /printf ("%d\n" ,(t+8)==t [8]) ; / 1 /l’operateur ++ fonctionne sur les pointeurs :int tab[]=f1 ,2g;int t = tab ;printf ("%d\n" ,t [0]) ; / 1 /t++;printf ("%d\n" ,t [0]) ; / 2 /4/22Structures et pointeursune structure (resp une union ou une enum) peut avoir ...
pointeur=adresseme´moire+type type* nom; nompointesurunezonem´emoirecorrespondant au nne type do ´ letypepeutˆetrequelconque valeursp´eciale NULL ´equivalentea`0 pointeurge´ne´rique: void* nom; l’ ´rateur & donne l’adresse d’une variable ope &*t==tpuisquel’adressedelavariablepoint´eepart...estt
#i n c l u d e < s t d i o . h > i n t main ( i n t a r g c , c h a r ∗ a r g v [ ] ) { i n t i ; i n t ∗ t = & i ; p r i n t f ( " % d \ n " ,& ∗ t==t ) ; / ∗ 1 ∗ /
}
/222
Passage par adresse
v o i d swap ( i n t a , i n t b ) { i n t tmp = a ; a = b ; b = tmp ; }
i n t main ( i n t a r g c , c h a r ∗∗ a r g v ) { i n t a = 5 , b = 1 0 ; s w a p t ( a , b ) ; p r i n t f ( " a = % d , b = % d " , a , b ) ; / ∗ a = 5 , b = 10 ∗ / }
v o i d swap ( i n t ∗ a , i n t ∗ b ) { i n t tmp = ∗ a ; ∗ a = ∗ b ; ∗ b = tmp ; }
i n t main ( i n t a r g c , c h a r ∗∗ a r g v ) { i n t a = 5 , b = 1 0 ; s w a p t (&a ,& b ) ; p r i n t f ( " a = % d , b = % d " , a , b ) ; / ∗ a = 1 0 , b = 5 ∗ / }
/322
Arith´etiquedespointeu m rs
int* t on peut voir t comme un tableau d’ int : *t = t[0] l’addition et la soustraction se font en fonction de la taille des ´ele´mentsdutableau
d o u b l e t [ 1 0 ] ; p r i n t f ( " % d \ n " , t +2==( v o i d ∗ ) t +2 ∗ s i z e o f ( d o u b l e ) ) ; / ∗ 1 ∗ / p r i n t f ( " % d \ n " , ∗ ( t +8)==t [ 8 ] ) ; / ∗ 1 ∗ /
l’ope´rateur++fonctionnesurlespointeurs:
i n t t a b [ ] = { 1 , 2 } ; i n t ∗ t = t a b ; p r i n t f ( " % d \ n " , t [ 0 ] ) ; / ∗ 1 ∗ / t ++; p r i n t f ( " % d \ n " , t [ 0 ] ) ; / ∗ 2 ∗ /
/422
Structures et pointeurs
une structure (resp une union ou une enum) peut avoir des champs de type pointeurs acce`sauchamppar nom struct.nom champ acce`sa`lavaleurpoint´eepar *(nom struct.nom champ) `anepasconfondreavec (*nom struct).nom champ quis’´ecritaussi nom struct->nom champ qui permet d’acceder au champs d’une structure dont on a ´ l’adresse
5/22
#i n c l u d e < s t d i o . h > t y p e d e f s t r u c t i n t A r r a y { i n t ∗ d a t a ; i n t c a p a c i t y ; i n t c u r r e n t ; } I n t A r r a y ; v o i d p r i n t I n t A r r a y ( I n t A r r a y ∗ a r r a y ) { i n t i ; f o r ( i =0; i < ( ∗ a r r a y ) . c u r r e n t ; i ++) { p r i n t f ( " % d " , ∗ ( ( ∗ a r r a y ) . d a t a )+ i ) ; / ∗ p r i n t f ( " % d " , ∗ ( ( a r r a y − > d a t a )+ i ) ) ; / ∗ p r i n t f ( " % d " , a r r a y − > d a t a [ i ] ) ; / ∗ } p r i n t f ( " \ b \ n " ) ; } i n t main ( i n t a r g s , c h a r ∗ a r g v [ ] ) { i n t t a b [ 5 ] = { 1 , 2 , 3 , 0 , 0 } ; I n t A r r a y a r r a y = { t a b , 5 , 3 } ; p r i n t I n t A r r a y (& a r r a y ) ; r e t u r n 0 ;
}
! ! ! ! ! ! : )
∗ / ∗ / ∗ /
Note:le”plus”estprioritairesurl’´etoile,maismieuxvaut parentheser quand meme
6/22
Transtypage
pasdeproble`medeconversionpour: void* vers void* truc* vers truc* truc* vers void * void* vers truc*
proble`mepourtruc1*verstruc2*
il faut une conversion explicite (cast) :
t r u c 1 ∗ b = ; . . . t r u c 2 ∗ t =( t r u c 2 ∗ ) b ;
7/22
Exemple d’utilisation
´ Ecrire une fonction qui retourne le codage des entiers sur la machine?Oninterpre`teunintcommeuntableaudechar,eton testlepremier´el´ement.
enum { BIG ENDIAN , LITTLE ENDIAN , BIG ENDIAN SWAP , LITTLE ENDIAN SWAP } ; i n t e n d i a n n e s s ( ) { u n s i g n e d i n t i =0x 1 2 3 4 5 6 7 8 ; u n s i g n e d c h a r ∗ t =( u n s i g n e d c h a r ∗ ) (& i ) ; s w i t c h ( t [ 0 ] ) { / ∗ 12 34 56 78 ∗ / c a s e 0 x 1 2 : r e t u r n BIG ENDIAN ; / ∗ 78 56 34 12 ∗ / c a s e 0 x 7 8 : r e t u r n LITTLE ENDIAN ; / ∗ 34 12 78 56 ∗ / c a s e 0 x 3 4 : r e t u r n BIG ENDIAN SWAP ; / ∗ 56 78 12 34 ∗ / d e f a u l t : r e t u r n LITTLE }
}
ENDIAN SWAP ;
8/22
Allocation dynamique
principe:demanderunezoneme´moireausyst`eme(peutdonc echouer !) ´ lesyst`emerenvoitl’adressedelazone,doncunpointeur cette zone est prise sur le tas etestpersistante(r´eserve´e)jusqu’`acequ’ellesoitlib´er´ee explicitement(contrairementauxvariableslocalesallou´eessur la pile)
/922
malloc
v o i d ∗ m a l l o c ( s i z e t s i z e ) ;
de´finiedansstdlib.h size=tailleenoctetsdelazoner´lam´ee ec retourne : lavaleurspe´cialeNULLencasd’´echec l’adressed’unezoneaucontenuind´efinisinon le type de reour est void* :pasbesoindoncd’´ecrirelecast explicitement maisenpratiqueonl’e´crit,´eviteleserreursbˆetes!
012/2
Re`glesd’ordumalloc
toujours tester le retour de malloc (puisque la fonction peut ´echouer!) toujoursmultiplierlenombred’e´le´mentsparlataille toujoursmettreuncastpourindiquerletype(lisibilite´) usage prototypique (allocation d’un tableau de 10 entiers) :
i n t ∗ t =( i n t ∗ ) m a l l o c ( 1 0 ∗ s i z e o f ( i n t ) ) ; i f ( t==NULL ) { f p r i n t f ( s t d e r r , " No t e n o u g h m e m o r y !\ n " ) ; e x i t ( 1 ) ; }