Pointeurs et références en C + + Partie 1

Avril 19, 2009 Posted in C / C + +

Pointeurs et les références sont deux concepts importants en science informatique. Ils apparaissent dans de nombreux langages de programmation avec une robe ou un peu différent, mais au fond, le traitement est le même. En C + +, avec les pointeurs sont des compétences essentielles.

Pointeur est un type spécial de données, les variables dont l'objectif déclaré de ce type mai (ou non) à d'autres données en mémoire. Une variable de type pointeur contient l'adresse d'une autre chose dans la mémoire. Cette chose peut être une variable, constante, le début d'un ensemble de données, une fonction, entre autres.

Déclarer des pointeurs

La déclaration d'un pointeur est généralement fait en ajoutant un astérisque devant le nom de variable. Une notation utilisé beaucoup la colle * le nom du type-à-dire symboliquement que déclare un pointeur "à type" au lieu d'une variable "pointeur", mais ils sont équivalents. Par exemple:

  / / Pointeur vers un int.
 ptr_num1 ; int * ptr_num1;

 / / Ou faire.
 ptr_num2 ; int * ptr_num2;

 / / Pointeur vers un double.
 ptr_double1 ; double * ptr_double1;

 / / Ou faire.
 ptr_double2 ; double * ptr_double2; 

Une fois déclarée, le pointeur se trouve, est de taille et prend donc place dans la mémoire. La taille d'un pointeur est généralement égal au nombre de bits de la machine / système en question, par exemple 4 octets dans un environnement 32 bits.

  17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 pc ; int i, * pi ; double d, * pd ; // O operador sizeof diz o tamanho do tipo do seu argumento. cout << "Size of char:    " << sizeof ( c ) << " bytes" << endl ; cout << "Size of int:     " << sizeof ( i ) << " bytes" << endl ; cout << "Size of double:  " << sizeof ( d ) << " bytes" << endl ; cout << endl ; cout << "Size of char*:   " << sizeof ( pc ) << " bytes" << endl ; cout << "Size of int*:    " << sizeof ( pi ) << " bytes" << endl ; cout << "Size of double*: " << sizeof ( pd ) << " bytes" << endl ; char c, * pc, int i, * pi, Double D, * pd; / / L'opérateur sizeof dit la taille du type de son argument. cout << "Taille du char:" <<sizeof (c) << " octets "<<endl cour <<" Size of int: "<<sizeof (i) <<" octets "<<endl cour <<" Taille du double: "<<sizeof (d) <<" octets " <<tribunal endl <<endl cour << "Taille du char *:" <<sizeof (PC) << "octets" <<endl cour << "Size of int *:" <<sizeof (pi) << "octets" <<endl cour << "Taille du double *" <<sizeof (pd) << "octets" <<endl; 

Avec des pointeurs

Après sa déclaration, le contenu d'un pointeur est une valeur aléatoire, les déchets de la mémoire, comme n'importe quelle variable. Pour qu'elle soit utile, nous devons lui donner quelque chose. En tant que pointeur contient une adresse mémoire, on lui attribue une adresse valide.

  17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
  int x, y;
 px, * py ; int * px, * py;

 ; x = 13;
 ; y = 10;

 x ; px = & x;
 y ; & Py = y;

 42 ; * Px = 42;
 py ) ++ ; (* Py) + +;

 * px << endl ; <<* px cout <<endl;
 * py << endl ; <<* py <<endl;
 ( * px ) * ( * py ) << endl ; cout <<(* px) * (* py) <<endl; 

L'opérateur & (et commercial ou esperluette) devant le nom d'un moyen variable "adresse", parce que son nom est "adresse".

Ce qui reste de l'égalité doit être en mesure de tenir exactement le même type qui est de l'autre côté de l'égalité. A magasins pointeur d'une adresse. Ainsi, pour attribuer une adresse à un pointeur, dans ce cas, vous devez obtenir une adresse avec l'opérateur &.

Sauf dans le cas où il ya des conversions de type implicites (comme entre les types numériques), affecter une variable à quelque chose avec un type différent de ses provoque une erreur de compilation. Heureusement!

Après un pointeur doit pointer vers une adresse valide, nous pouvons accéder au contenu de cette adresse avec l'opérateur * (astérisque), dont le nom officiel est «opérateur de référence.

Notez que l'astérisque dans une déclaration signifie «pointeur de taper" dans le contexte de la lecture ou l'écriture du contenu d'un pointeur, signifie "le contenu de l'adresse» ou «le contenu pointé par. Également veiller à ne pas confondre avec le symbole pour l'arithmétique des produits. Pour éviter toute confusion, rappelons que immense table de préséance des opérateurs, que vous venez de passer les yeux et se laissa tomber dans l'oubli. Ici vous trouverez que l'opérateur de référence a priorité sur l'opérateur de multiplication. Une fois que c'est fait, vous vous souvenez que l'exploitant de référence est évalué avant que l'opérateur de multiplication.

  17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
  pa, * pb ; int a, b, c, * pa, * pb;
 ; a = 2;
 ; b = 3;

 a ; pa = & a;
 b ; PB = & b;

 pa * * pb ; c pa = * * * pb;
 pa * * pb ; c pa = * * * pb;
 pa * * pb ; c pa = * * * pb;
 pa ** pb ; c = * pa ** pb;
 * pa ) * ( * pb ) ; c = (* pa) * (* pb);

 "Valor da Pegadinha: " << c << endl ; cout << "Valeur Anecdote:" <<c <<endl; 

Ainsi, lorsque que des preuves d'algorithmes de vous demander ce qui fait l'une des 5 dernières lignes de l'exemple que vous diront qu'il multiplie le contenu pointé par PA et PB. Il aura pour ramasser PD pour cette raison! Et la rupture dans la vie réelle, si vous avez vraiment besoin pour ce faire, vous pourrez enregistrer vos 4 générations passées et futures de 5 excommunication, si vous choisissez d'utiliser la dernière ligne.

Tout ce que vous pouvez faire avec une variable commune, vous pouvez faire avec le contenu pointé par un pointeur, soit la lecture ou d'écriture (sauf s'il est clair que le pointeur est const, mais c'est une autre ...). Rant

Adresses et pointeurs

Prenez par exemple le code ci-dessous:

  18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
  int a, b;
 pa, * pb ; int * pa, * pb;

 "Antes de qualquer atribuição: \n " ) ; printf ( "Avant toute cession: \ n");

 "&a  = %p \n " , & a ) ; // Endereço válido dado pelo SO. printf ( "& a =% p \ n", & a) / / adresse valide étant donné par l'OS.
 "&b  = %p \n " , & b ) ; // Endereço válido dado pelo SO. printf ( "& b =% p \ n", & b) / / adresse valide étant donné par l'OS.
 "&pa = %p \n " , & pa ) ; // Endereço válido dado pelo SO. printf ( "& pa =% p \ n", & PA); / / adresse valide étant donné par l'OS.
 "&pb = %p \n " , & pb ) ; // Endereço válido dado pelo SO. printf ( "& pb =% p \ n", & pb); / / adresse valide étant donné par l'OS.

 " \n " ) ; printf ( "\ n");

 "a   = %d \n " , a ) ; // Conteúdo não inicializado (aleatório). printf ( "a =% d \ n", a); / / Content initialisés (aléatoire).
 "b   = %d \n " , b ) ; // Conteúdo não inicializado (aleatório). printf ( "b =% d \ n", b) / / Contenu non initialisée (aléatoire).
 "pa  = %p \n " , pa ) ; // Conteúdo não inicializado (aleatório). printf ( "p =% pa \ n", pa) / / Contenu non initialisée (aléatoire).
 "pb  = %p \n " , pb ) ; // Conteúdo não inicializado (aleatório). printf ( "= P bp% \ n", pb); / / Content initialisés (aléatoire).

 / / S'il vous plaît décommenter les lignes suivantes, recompiler et exécuter.
 / / Printf ( "* pa =% d \ n", * pa) / / Quel sera (random *)?
 / / Printf ( "* PB =% d \ n", * pb); / / Quelle est (random *)?

 " \n Após as inicializações dos ponteiros: \n " ) ; n printf ( "\ Après l'initialisation des pointeurs: \ n");

 a ; pa = & a;
 b ; PB = & b;

 "&a  = %p \n " , & a ) ; // Mesmo endereço válido dado pelo SO. printf ( "& a =% p \ n", & a); / / adresse valide Même donnée par l'OS.
 "&b  = %p \n " , & b ) ; // Mesmo endereço válido dado pelo SO. printf ( "& b =% p \ n", & b) / / Même adresse valide étant donné par l'OS.
 "&pa = %p \n " , & pa ) ; // Mesmo endereço válido dado pelo SO. printf ( "& pa =% p \ n", & PA); / / adresse valide Même donnée par l'OS.
 "&pb = %p \n " , & pb ) ; // Mesmo endereço válido dado pelo SO. printf ( "& pb =% p \ n", & pb); / / adresse valide Même donnée par l'OS.

 " \n " ) ; printf ( "\ n");

 "a   = %d \n " , a ) ; // Conteúdo não inicializado (aleatório). printf ( "a =% d \ n", a); / / Content initialisés (aléatoire).
 "b   = %d \n " , b ) ; // Conteúdo não inicializado (aleatório). printf ( "b =% d \ n", b) / / Contenu non initialisée (aléatoire).
 "pa  = %p \n " , pa ) ; // Conteúdo inicializado (&a). printf ( "p =% pa \ n", pa) / / Content initialisé (& A).
 "pb  = %p \n " , pb ) ; // Conteúdo inicializado (&b). printf ( "= P bp% \ n", pb); / / Content initialisé (& b).

 "*pa = %d \n " , * pa ) ; // Conteúdo apontado por pa (*pa == a). printf ( "* pa =% d \ n", * pa); / / Content nommé par an (* pa == a).
 "*pb = %d \n " , * pb ) ; // Conteúdo apontado por pb (*pb == b). printf ( "* PB =% d \ n", * pb); / / le contenu pointé par pb (* pb == b).

 " \n Após as inicializações dos inteiros: \n " ) ; n printf ( "\ Après l'initialisation des nombres entiers: \ n");

 ; a = 10;
 ; b = 13;

 "&a  = %p \n " , & a ) ; // Mesmo endereço válido dado pelo SO. printf ( "& a =% p \ n", & a); / / adresse valide Même donnée par l'OS.
 "&b  = %p \n " , & b ) ; // Mesmo endereço válido dado pelo SO. printf ( "& b =% p \ n", & b) / / Même adresse valide étant donné par l'OS.
 "&pa = %p \n " , & pa ) ; // Mesmo endereço válido dado pelo SO. printf ( "& pa =% p \ n", & PA); / / adresse valide Même donnée par l'OS.
 "&pb = %p \n " , & pb ) ; // Mesmo endereço válido dado pelo SO. printf ( "& pb =% p \ n", & pb); / / adresse valide Même donnée par l'OS.

 " \n " ) ; printf ( "\ n");

 "a   = %d \n " , a ) ; // Conteúdo inicializado (10). printf ( "a =% d \ n", a); / / Chaussures de contenu (10).
 "b   = %d \n " , b ) ; // Conteúdo inicializado (13). printf ( "b =% d \ n", b) / / bottes de contenu (13).
 "pa  = %p \n " , pa ) ; // Conteúdo inicializado (&a). printf ( "p =% pa \ n", pa) / / Content initialisé (& A).
 "pb  = %p \n " , pb ) ; // Conteúdo inicializado (&b). printf ( "= P bp% \ n", pb); / / Content initialisé (& b).

 "*pa = %d \n " , * pa ) ; // Conteúdo apontado por pa (*pa == a == 10). printf ( "* pa =% d \ n", * pa); / / Content nommé par an (* pa == a == 10).
 "*pb = %d \n " , * pb ) ; // Conteúdo apontado por pb (*pb == b == 13). printf ( "* PB =% d \ n", * pb); / / le contenu pointé par pb (* pb == b == 13).

 " \n Alterando os valores através dos ponteiros: \n " ) ; printf ( "\ n La modification des valeurs par un pointeur: \ n");

 7 ; * Pa = 7;
 42 ; * Pb = 42;

 "&a  = %p \n " , & a ) ; // Mesmo endereço válido dado pelo SO. printf ( "& a =% p \ n", & a); / / adresse valide Même donnée par l'OS.
 "&b  = %p \n " , & b ) ; // Mesmo endereço válido dado pelo SO. printf ( "& b =% p \ n", & b) / / Même adresse valide étant donné par l'OS.
 "&pa = %p \n " , & pa ) ; // Mesmo endereço válido dado pelo SO. printf ( "& pa =% p \ n", & PA); / / adresse valide Même donnée par l'OS.
 "&pb = %p \n " , & pb ) ; // Mesmo endereço válido dado pelo SO. printf ( "& pb =% p \ n", & pb); / / adresse valide Même donnée par l'OS.

 " \n " ) ; printf ( "\ n");

 "a   = %d \n " , a ) ; // Conteúdo inicializado (a == *pa ==  7). printf ( "a =% d \ n", a) / / Début secteur de contenu (a == * PA == 7).
 "b   = %d \n " , b ) ; // Conteúdo inicializado (b == *pb == 42). printf ( "b =% d \ n", b) / / Content initialisé (b == * pb == 42).
 "pa  = %p \n " , pa ) ; // Conteúdo inicializado (&a). printf ( "p =% pa \ n", pa) / / Content initialisé (& A).
 "pb  = %p \n " , pb ) ; // Conteúdo inicializado (&b). printf ( "= P bp% \ n", pb); / / Content initialisé (& b).

 "*pa = %d \n " , * pa ) ; // Conteúdo apontado por pa ( 7). printf ( "* pa =% d \ n", * pa); / / Content nommé par an (7).
 "*pb = %d \n " , * pb ) ; // Conteúdo apontado por pb (42). printf ( "* PB =% d \ n", * pb); / / le contenu pointé par PB (42). 

La ligne 18 et 19, il a déclaré respectivamnete deux et deux pointeurs sur des entiers.

Les lignes 23 à 26 montre l'adresse de mes variables. Ces adresses ont été données par le système d'exploitation et sont fixes, tandis que les variables existent. Une variable ne change pas d'adresse en cours du programme, mais peut changer entre une exécution et un autre. Qui définit ce que cette adresse est le système d'exploitation au moment du programme. Le compilateur sait seulement que X octets sont nécessaires pour chaque variable, et l'interprétation (de style) que le programme permettra de donner cet espace.

Lignes 30 à 33 montrent le contenu de ces variables, qui n'ont pas été initialisé. Il s'agit des ordures, la dernière valeur que quelqu'un (je ne sais pas qui) mettent ces lieux à la mémoire d'ordinateur et qui font aujourd'hui partie de mes variables.

Notez qu'il est sécuritaire de décommenter les lignes 36 et 37 car ils essaient d'accéder au contenu pointé par PA et PB, qui n'a pas été initialisé. Au cours de cette tentative, le programme va essayer d'interpréter ces valeurs d'ordures aléatoires comme s'ils sont des adresses de variables int valide. Selon le compilateur, le système d'exploitation utilisés et leur sort mai être inoffensifs ou non. Ce qui est certain c'est que le résultat de ces lignes est imprévisible et source sûre de problèmes.

Dans les lignes 41 et 42, les pointeurs sont initialisés avec les adresses des variables entières a et b. Depuis lors, les estampes sont répétées.

Notez que les adresses des pointeurs ne changent pas, ce qui était attendu. Quels sont les changements de son contenu. PA Variables et pb recevoir les adresses de A et B respectivement. Notez que le contenu de la main est exactement la valeur de l'adresse des variables A et B qui ont été données par l'OS au début du programme. Vérifiez auprès de l'affiche ci-dessus. Le contenu pointé par PA et PB est le contenu même de A et B, qui n'a pas été initialisé, c'est à dire, les ordures. Cependant, contrairement à l'étape précédente, maintenant des pointeurs vers des adresses valides (adresses de A et B) et que le contenu de a et b sont des pointeurs de la mémoire des ordures pointent maintenant aux variables qui ont été attribués.

Dans les lignes 61 et 62, les variables entières sont initialisés avec les valeurs 10 et 13, et les tirages répété.

Cette fois, le coteúdos de a et b sont des ordures non plus. Les valeurs sont bien connus. Notez qu'il n'y a pas de changement dans l'adressage de variables par rapport aux étapes précédentes, seules les valeurs.

Voir aussi que, après A et B ont été initialisés, le contenu pointé par PA et PB ont également été modifiées automatiquement. Cela se produit justement parce que PA et le point de PB pour les mêmes zones de mémoire utilisée par PA variables et pb. Cela signifie que le contenu pointé par un pointeur peut être modifiée en changeant le contenu des variables d'origine a fait observer par lui. Et enfin, les lignes 81 à 97 montrent que l'inverse est également vrai, c'est à dire, en changeant le contenu pointé par un pointeur, pour modifier automatiquement le contenu des variables d'origine a fait observer par eux.

Il est plus facile à comprendre cette réflexion sur les phrases en portugais que de regarder le code.

Pour le moment ...

Ce fut le fonctionnement de base contenant des pointeurs. Il ya encore des choses intéressantes à être considérés comme des pointeurs vers des fonctions, par exemple, mais qui est considérée comme un sujet plus avancé. À la suite de cette série, qui est prévu pour 4 postes, voir les références, les différences et les similitudes entre les pointeurs et les références et, enfin, les pointeurs de fonctions.

Liens

Commentaires

5 réponses à "Pointeurs et références en C + + Part 1"

  1. [...] Avec cette tentative de série de messages concernant les pointeurs et les références, qui commença à parler de pointeurs, discuter aujourd'hui [...]

  2. [...] [...] Pointeiros et références

  3. [...] Premier post de cette série, nous parler un peu de pointeurs. Dans le second, on parle de références. Aujourd'hui nous allons nous concentrer sur la relation intime (ui!) Entre les pointeurs et [...]

  4. Fernando sur Décembre 26, 2009 18:50

    Mec, tu as à me montrer comment qui fait de vous envoyer le code que vous a posté?
    Intérieur d'une zone en particulier, le marquage des lignes et en soulignant les mots-clés de la langue?

  5. blab le 28 Décembre 2009 08:48

    Pas de problème!

    Le Wordpress est un plugin appelé WP-Syntax, qui utilise les coulisses du GeSHi.

    Une fois installé, vous pouvez mettre votre code entre les balises d'PRE, en ajoutant des attributs de la «langue» et «en ligne». La langue est auto-explicatif et dispose d'une liste de langues dans la documentation et la ligne est la ligne de départ.

    Le GeSHi peut également être exploité pour ajouter cette fonctionnalité dans les wikis.

    Astuce: Avant de copier et coller le code, remplacez tous les onglets de 4 espaces. Cela rendra le code indépendant du style appliqué à l'onglet.

    Hugs

Laissez une réponse




Powered by WP Hashcash