Que signifie pour déréférencer un pointeur? Puis-je s'il vous plaît obtenir une explication avec un exemple?
Réponses
Trop de publicités?L'examen de la terminologie de base
(En utilisant la terminologie un peu lâche pour le rendre facile à comprendre...)
Un pointeur contient un numéro d'identification d'une adresse de mémoire, avec:
- 0 référence pour le premier octet dans la mémoire du processus d'adresse / de l'espace,
- 1 est le deuxième octet, et ainsi de suite....
Lorsque vous souhaitez accéder aux données/valeur dans la mémoire que le pointeur pointe vers le contenu de l'adresse avec index numérique - alors vous déréférencer le pointeur.
Différents langages informatiques ont notations différentes pour indiquer au compilateur ou l'interpréteur vous êtes intéressé dans le fait-pour la valeur, je me concentre ci-dessous sur le C et le C++.
Un pointeur scénario
Considérons en C, un pointeur comme p
ci-dessous...
const char* p = "abc";
...quatre octets avec les valeurs numériques utilisées pour coder les lettres 'a', 'b', 'c', et un 0 octet pour indiquer la fin des données textuelles, sont stockées quelque part dans la mémoire et l'adresse numérique de données est stocké dans p
.
Par exemple, si la chaîne de caractères littérale qui est arrivé à être à l'adresse 0x1000 et p
pointeur de 32 bits à 0x2000, le contenu de la mémoire serait:
Memory Address (hex) Variable name Contents
1000 'a' == 97 (ASCII)
1001 'b' == 98
1002 'c' == 99
1003 0
...
2000-2003 p 1000 hex
Notez qu'il n'existe pas de variable nom/identifiant de l'adresse 0x1000, mais nous pouvons indirectement, reportez-vous à la chaîne littérale à l'aide d'un pointeur de stocker son adresse: p
.
Un déréférencement du pointeur
Pour consulter les caractères p
de points à nous de déréférencement p
l'aide de l'une de ces notations (encore une fois, C):
assert(*p == 'a'); // the first character at address p will be 'a'
assert(p[1] == 'b'); // p[1] actually dereferences a pointer created by adding
// p and 1 times the size of the things to which p points:
// in this case they're char which are 1 byte in C...
assert(*(p + 1) == 'b'); // another notation for p[1]
Vous pouvez également déplacer les pointeurs par le biais de la pointe-aux données, de déférence au fur et à mesure:
++p; // increment p so it's now 0x1001
assert(*p == 'b'); // p == 0x1001 which is where the 'b' is...
Si vous avez quelques données qui peut être écrit à, alors vous pouvez faire des choses comme ceci:
int x = 2;
int* p_x = &x; // put the address of the x variable into the pointer p_x
*p_x = 4; // change the memory at the address in p_x to be 4
assert(x == 4); // check x is now 4
Ci-dessus, vous devez avoir connu au moment de la compilation que vous avez besoin d'une variable nommée x
, et le code demande au compilateur d'organiser là où il doit être stocké, en veillant à l'adresse sera disponible via &x
.
De déférence et de l'accès à une structure de données des membres
En C, si vous avez variable qui est une structure de données des membres, vous pouvez accéder à ces membres à l'aide de l' ->
opérateur de déréférencement:
typedef struct X { int i_; double d_; } X;
X x;
X* p = &x;
p->d_ = 3.14159; // dereference and access data member x.d_
(*p).d_ *= -1; // another equivalent notation for accessing x.d_
Multi-octets types de données
L'utilisation d'un pointeur, un programme d'ordinateur doit également quelques indications sur le type de données qui est en cours pointé - si ce type de données besoin de plus d'un octet pour représenter, alors que le pointeur normalement points pour le plus petit numéro de l'octet de données dans les données.
Donc, en regardant un exemple légèrement plus complexe:
double sizes[] = { 10.3, 13.4, 11.2, 19.4 };
double* p = sizes;
assert(p[0] == 10.3); // knows to look at all the bytes in the first double value
assert(p[1] == 13.4); // actually looks at bytes from address p + 1 * sizeof(double)
// (sizeof(double) is almost always eight bytes)
assert(++p); // advance p by sizeof(double)
assert(*p == 13.4); // the double at memory beginning at address p has value 13.4
*(p + 2) = 29.8; // change sizes[3] from 19.4 to 29.8
Des pointeurs vers la mémoire allouée dynamiquement
Parfois, vous ne savez pas combien de mémoire vous aurez besoin jusqu'à ce que votre programme est en cours d'exécution et voit ce que les données sont jetées... alors vous pouvez allouer dynamiquement de la mémoire à l'aide de malloc
. Il est de pratique courante pour stocker l'adresse dans un pointeur...
int* p = malloc(sizeof(int)); // get some memory somewhere...
*p = 10; // dereference the pointer to the memory, then write a value in
fn(*p); // call a function, passing it the value at address p
(*p) += 3; // change the value, adding 3 to it
free(p); // release the memory back to the heap allocation library
En C++, l'allocation de mémoire est normalement fait avec l' new
de l'opérateur, et la désallocation avec delete
:
int* p = new int(10); // memory for one int with initial value 10
delete p;
p = new int[10]; // memory for ten ints with unspecified initial value
delete[] p;
p = new int[10](); // memory for ten ints that are value initialised (to 0)
delete[] p;
La perte et de la fuite des adresses
Souvent, un pointeur peut être la seule indication de l'endroit où certaines données ou de la mémoire tampon existe dans la mémoire. Si l'utilisation de données/tampon est nécessaire, ou la possibilité de faire appel free()
ou delete
pour éviter des fuites de mémoire, le programmeur doit utiliser une copie du pointeur...
const char* p = asprintf("name: %s", name); // common but non-Standard printf-on-heap
// replace non-printable characters with underscores....
for (const char* q = p; *q; ++q)
if (!isprint(*q))
*q = '_';
printf("%s\n", p); // only q was modified
free(p);
...ou soigneusement orchestrer le renversement de tous les changements...
const size_t n = ...;
p += n;
...
p -= n; // restore earlier value...
Un déréférencement d'un pointeur signifie obtenir la valeur qui est stockée dans l'emplacement mémoire pointé par le pointeur. L'opérateur * est utilisée pour faire cela, et il est appelé l'opérateur de déréférencement.
int a = 10;
int* ptr = &a;
printf("%d", *ptr); // With *ptr I'm dereferencing the pointer.
// Which means, I am asking the value pointed at by the pointer.
// ptr is pointing to the location in memory of the variable a.
// In a's location, we have 10. So, dereferencing gives this value.
// Since we have indirect control over a's location, we can modify its content using the pointer. This is an indirect way to access a.
*ptr = 20; // Now a's content is no longer 10, and has been modified to 20.
Un pointeur est une "référence" à une valeur.. un peu comme une bibliothèque numéro d'appel est une référence à un livre. "Déréférencement" le numéro d'appel est physiquement et la récupération de ce livre.
int a=4 ;
int *pA = &a ;
printf( "The REFERENCE/call number for the variable `a` is %p\n", pA ) ;
// The * causes pA to DEREFERENCE... `a` via "callnumber" `pA`.
printf( "%d\n", *pA ) ; // prints 4..
Si le livre n'est pas là, le bibliothécaire se met à crier, ferme la bibliothèque vers le bas, et un couple de gens sont mis à enquêter sur la cause d'une personne va trouver un livre qui n'est pas là.
Code et l'explication de Pointeur de Bases:
Le déréférencement de l'opération démarre à le pointeur, et suit sa flèche sur pour accéder à ses pointee. L'objectif peut être regarder le pointee de l'état ou à modifier la pointee état. L' opération de déréférence un pointeur sur ne fonctionne que si le pointeur a une pointee -- le pointee doit être alloués et le pointeur doit être défini pour pointer vers elle. L'erreur la plus commune dans le code de pointeur, c'est d'oublier de définir le pointee. Les plus courantes runtime planter à cause de cette erreur de le code est un échec de déréférencement le fonctionnement. En Java, les incorrecte déréférencer sera marqué poliment par le système d'exécution. Dans compilé des langages tels que C, C++, Pascal, la mauvaise déréférencement va parfois, crash, et d'autres fois corruption de la mémoire dans certains subtil, aléatoire façon. Pointeur de bugs dans compilé les langues peuvent être difficiles à suivre bas pour cette raison.
void main() {
int* x; // Allocate the pointer x
x = malloc(sizeof(int)); // Allocate an int pointee,
// and set x to point to it
*x = 42; // Dereference x to store 42 in its pointee
}