Pointers and references in C + + Part 1
Pointers and references are two important concepts in computer science. They appear in many programming languages with a dress or a little different, but the treatment is basically the same. In C + +, with pointers skills are essential.
Pointer is a special type of data, variables whose declared aim of this kind may (or not) to some other data in memory. A pointer variable, holds the address of one other thing in memory. This thing can be a variable, constant, initiation of a data set, a function, among others.
Declaring Pointers
The declaration of a pointer is usually done by appending a * before the variable name. A notation used much the glue * the name of the type to say symbolically that is declaring a "pointer to type" instead of a "pointer variable", but they are equivalent. For example:
/ / Pointer to an int. ptr_num1 ; int * ptr_num1; / / Or so. ptr_num2 ; int * ptr_num2; / / Pointer to a double. ptr_double1 ; double * ptr_double1; / / Or so. ptr_double2 ; double * ptr_double2;
Once declared, the pointer exists, has size and consequently takes place in memory. The size of a pointer is usually equal to the number of bits of the machine / system in question, eg 4 bytes in a 32-bit system.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 | pc ; char c, * pc; pi ; int i, * pi; pd ; double d, * pd; / / The sizeof operator says the size of the type of its argument. "Size of char: " << sizeof ( c ) << " bytes" << endl ; court <<"Size of char:" <<sizeof (c) <<"bytes" <<endl; "Size of int: " << sizeof ( i ) << " bytes" << endl ; court <<"Size of int:" <<sizeof (i) <<"bytes" <<endl; "Size of double: " << sizeof ( d ) << " bytes" << endl ; court <<"Size of double:" <<sizeof (d) <<"bytes" <<endl; endl ; court <<endl; "Size of char*: " << sizeof ( pc ) << " bytes" << endl ; court <<"Size of char *:" <<sizeof (cp) <<"bytes" <<endl; "Size of int*: " << sizeof ( pi ) << " bytes" << endl ; court <<"Size of int *:" <<sizeof (pi) <<"bytes" <<endl; "Size of double*: " << sizeof ( pd ) << " bytes" << endl ; court <<"Size of double *" <<sizeof (pd) <<"bytes" <<endl; |
Using Pointers
After his statement, the contents of a pointer is a random value, garbage memory, like any variable. For it to be useful we need to give him something. As a pointer holds a memory address, we must assign it a valid address.
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 ; court <<* px <<endl; * py << endl ; court <<* py <<endl; ( * px ) * ( * py ) << endl ; court <<(* px) * (* py) <<endl; |
The operator & (ampersand or ampersand ) before a variable name means "address", because his name is "address."
What's left of the equality has to be able to keep exactly the same kind than is the other side of equality. A pointer stores an address. So to assign an address to a pointer in this case, you need to get an address with the & operator.
Except in the case where there is implicit type conversions (such as between numeric types), assign a variable to something with a different type than his own, causing a compilation error. Fortunately!
After a pointer already points to a valid address, we can access the contents of this address with the operator * ( asterisk ), whose formal name is "de-reference operator."
Note that the asterisk in a statement means "pointer to type" and in the context of reading or writing the contents of a pointer, means "the contents of the address" or "the content pointed by". Also be careful not to confuse the symbol for arithmetic product. To avoid confusing, remember that huge table of precedence of operators , which you just passed the eye and dropped into oblivion. There you will find that the de-reference operator takes precedence over the multiplication operator. Then you will remember that the de-reference operator is evaluated before the multiplication operator.
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 ** bp; * pa ) * ( * pb ) ; c = (* pa) * (* pb); "Valor da Pegadinha: " << c << endl ; court <<"Value of Gotcha:" <<c <<endl; |
So when that proof of algorithms you ask what makes any one of the last five lines of the example you will say that it multiplies the contents pointed to by ap and bp. No more pick up DP for it! And breaking in real life, if you really need to do this, you will save your fourth and fifth generations past future excommunication , if you choose to use the last line.
Everything is possible with a common variable you can do with the content pointed to by a pointer, either reading or writing (unless it is clear that the pointer is const, but that's another conversation ...).
Addresses and Pointers
Take for example the code below:
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 ("Before any assignment: \ n"); "&a = %p \n " , & a ) ; // Endereço válido dado pelo SO. printf ("& a =% p \ n", & a) / / Valid address given by the OS. "&b = %p \n " , & b ) ; // Endereço válido dado pelo SO. printf ("& b =% p \ n", & b) / / Valid address given by the OS. "&pa = %p \n " , & pa ) ; // Endereço válido dado pelo SO. printf ("& pa =% p \ n", & pa) / / Valid address given by the OS. "&pb = %p \n " , & pb ) ; // Endereço válido dado pelo SO. printf ("& pb =% p \ n", & bp); / / Valid address given by the OS. " \n " ) ; printf ("\ n"); "a = %d \n " , a ) ; // Conteúdo não inicializado (aleatório). printf ("a =% d \ n", a); / / Content uninitialized (random). "b = %d \n " , b ) ; // Conteúdo não inicializado (aleatório). printf ("b =% d \ n", b) / / Content uninitialized (random). "pa = %p \n " , pa ) ; // Conteúdo não inicializado (aleatório). printf ("pa =% p \ n", pa) / / Content uninitialized (random). "pb = %p \n " , pb ) ; // Conteúdo não inicializado (aleatório). printf ("bp =% p \ n", pb); / / Content uninitialized (random). / / Please uncomment the following lines, recompile and run. / / Printf ("* pa =% d \ n", * pa) / / What is (random *)? / / Printf ("* pb =% d \ n", * pb) / / What is (random *)? " \n Após as inicializações dos ponteiros: \n " ) ; printf ("\ n After the initialization of pointers: \ n"); a ; pa = & a; b ; pb = & b; "&a = %p \n " , & a ) ; // Mesmo endereço válido dado pelo SO. printf ("& a =% p \ n", & a) / / Even valid address given by the OS. "&b = %p \n " , & b ) ; // Mesmo endereço válido dado pelo SO. printf ("& b =% p \ n", & b) / / Even valid address given by the OS. "&pa = %p \n " , & pa ) ; // Mesmo endereço válido dado pelo SO. printf ("& pa =% p \ n", & pa); / / same address as valid by the OS. "&pb = %p \n " , & pb ) ; // Mesmo endereço válido dado pelo SO. printf ("& pb =% p \ n", & bp); / / same address as valid by the OS. " \n " ) ; printf ("\ n"); "a = %d \n " , a ) ; // Conteúdo não inicializado (aleatório). printf ("a =% d \ n", a); / / Content uninitialized (random). "b = %d \n " , b ) ; // Conteúdo não inicializado (aleatório). printf ("b =% d \ n", b) / / Content uninitialized (random). "pa = %p \n " , pa ) ; // Conteúdo inicializado (&a). printf ("pa =% p \ n", pa) / / initialized Content (& a). "pb = %p \n " , pb ) ; // Conteúdo inicializado (&b). printf ("bp =% p \ n", pb); / / Content initialized (& b). "*pa = %d \n " , * pa ) ; // Conteúdo apontado por pa (*pa == a). printf ("* pa =% d \ n", * pa) / / content pointed to by ap (* pa == a). "*pb = %d \n " , * pb ) ; // Conteúdo apontado por pb (*pb == b). printf ("* pb =% d \ n", * pb) / / content pointed to by bp (bp == * b). " \n Após as inicializações dos inteiros: \n " ) ; printf ("\ n After the initializations of integers: \ n"); ; a = 10; ; b = 13; "&a = %p \n " , & a ) ; // Mesmo endereço válido dado pelo SO. printf ("& a =% p \ n", & a) / / Even valid address given by the OS. "&b = %p \n " , & b ) ; // Mesmo endereço válido dado pelo SO. printf ("& b =% p \ n", & b) / / Even valid address given by the OS. "&pa = %p \n " , & pa ) ; // Mesmo endereço válido dado pelo SO. printf ("& pa =% p \ n", & pa); / / same address as valid by the OS. "&pb = %p \n " , & pb ) ; // Mesmo endereço válido dado pelo SO. printf ("& pb =% p \ n", & bp); / / same address as valid by the OS. " \n " ) ; printf ("\ n"); "a = %d \n " , a ) ; // Conteúdo inicializado (10). printf ("a =% d \ n", a); / / Content starts (10). "b = %d \n " , b ) ; // Conteúdo inicializado (13). printf ("b =% d \ n", b) / / Content starts (13). "pa = %p \n " , pa ) ; // Conteúdo inicializado (&a). printf ("pa =% p \ n", pa) / / initialized Content (& a). "pb = %p \n " , pb ) ; // Conteúdo inicializado (&b). printf ("bp =% p \ n", pb); / / Content initialized (& b). "*pa = %d \n " , * pa ) ; // Conteúdo apontado por pa (*pa == a == 10). printf ("* pa =% d \ n", * pa) / / content pointed to by ap (* pa == a == 10). "*pb = %d \n " , * pb ) ; // Conteúdo apontado por pb (*pb == b == 13). printf ("* pb =% d \ n", * pb) / / content pointed to by pb (* pb == b == 13). " \n Alterando os valores através dos ponteiros: \n " ) ; printf ("\ n Changing values through pointers: \ n"); 7 ; * Pa = 7; 42 ; * Bp = 42; "&a = %p \n " , & a ) ; // Mesmo endereço válido dado pelo SO. printf ("& a =% p \ n", & a) / / Even valid address given by the OS. "&b = %p \n " , & b ) ; // Mesmo endereço válido dado pelo SO. printf ("& b =% p \ n", & b) / / Even valid address given by the OS. "&pa = %p \n " , & pa ) ; // Mesmo endereço válido dado pelo SO. printf ("& pa =% p \ n", & pa); / / same address as valid by the OS. "&pb = %p \n " , & pb ) ; // Mesmo endereço válido dado pelo SO. printf ("& pb =% p \ n", & bp); / / same address as valid by the OS. " \n " ) ; printf ("\ n"); "a = %d \n " , a ) ; // Conteúdo inicializado (a == *pa == 7). printf ("a =% d \ n", a); / / Content initialized (* pa == a == 7). "b = %d \n " , b ) ; // Conteúdo inicializado (b == *pb == 42). printf ("b =% d \ n", b) / / Content initialized (b == * pb == 42). "pa = %p \n " , pa ) ; // Conteúdo inicializado (&a). printf ("pa =% p \ n", pa) / / initialized Content (& a). "pb = %p \n " , pb ) ; // Conteúdo inicializado (&b). printf ("bp =% p \ n", pb); / / Content initialized (& b). "*pa = %d \n " , * pa ) ; // Conteúdo apontado por pa ( 7). printf ("* pa =% d \ n", * pa) / / Content appointed by pa (7). "*pb = %d \n " , * pb ) ; // Conteúdo apontado por pb (42). printf ("* pb =% d \ n", * pb) / / content pointed to by bp (42). |
Lines 18:19 respectivamnete declare two integer and two pointers to integers.
Lines 23-26 show the addresses of my variables. These addresses were given by the operating system and are fixed while these variables exist. A variable does not change address during the program, but can change between one execution and another. Who defines what that address is the operating system at the time of program implementation. The compiler only knows that x bytes are needed for each variable, and of the interpretation (style) that the program will give that space.
Lines 30-33 show the contents of these variables, which has not been initialized. It's garbage, the last value that someone (do not know who) put those places in computer memory and which now belong to my variables.
Note that it is not safe to uncomment lines 36 and 37 as they try to access the content pointed to by ap and bp, which has not been initialized. During this attempt, the program will try to interpret those values as if they were garbage random variables int valid addresses. Depending on the compiler, the OS used and their fate may be harmless or not. What is certain is that the outcome of these lines is unpredictable and sure source of problems.
On lines 41 and 42 the pointers are initialized with the addresses of the integer variables a and b. Since then the prints are repeated.
See the addresses of the pointers do not change, what was expected. What are its contents change. Variables pa and pb receive the addresses of a and b respectively. Note that the content of the hands is exactly the address value of the variables a and b that were given by the OS at the beginning of the program. Check with the prints above. The content pointed to by ap and bp is the same content and b, which has not been initialized, or trash. However, unlike the previous step, now the pointers point to valid addresses (addresses of a and b) and that the contents of a and b are garbage memory pointers now point to variables that have already been allocated.
On lines 61 and 62 the integer variables are initialized with the values 10 and 13, repeated again and prints.
This time the coteúdos of a and b are no longer junk. Values are properly known. Note that there is no change in the addressing of variables relative to the previous steps, only the values.
See also that after a and b have been initialized, the contents pointed to by ap and bp have also been changed automatically. This happens precisely because pa pb and point to the same memory areas used by the variables pa and pb. This means that the content pointed to by a pointer can be modified by changing the contents of the original variables pointed out by him. And finally, lines 81-97 show that the converse is also true, ie, changing the content pointed to by a pointer, automatically alters the content of the original variables they pointed out.
It is easier to understand this thinking in phrases in Portuguese than looking at the code.
For now ...
This was the basic operations with pointers. There are still interesting things to be seen as pointers to functions, for example, but that is considered a more advanced topic. Following this series, which is planned for four posts, see references, similarities and differences between pointers and references and finally pointers to functions.
Links
- ponteiros.zip (all sources of the post);
- 01-declaracao.cpp
- 02-tamanhos.cpp
- 03-utilizando.cpp
- 04-pegadinha.cpp
- 05-enderecos.cpp
- Pointers on cplusplus.com
- The Guilty
Comments
- Bruno
- blab
- Fernando


