Pointers and references in C + + Part 1
Pointers and references are two very 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 + +, pointers are essential skills.
Pointer is a special type of data, whose variables can declared such in (or not) to some other data in memory. A variable of type pointer holds the address of one other thing in memory. This thing can be any variable, constant, the beginning of a data set, a function, among others.
Declaring Pointers
The declaration of a pointer is usually done by adding a * before the variable name. A widely used notation * to paste the name of the type to say that we are symbolically 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 length and consequently takes place in memory. The size of a pointer is usually equal to the number of bits of the machine / system, for example 4 bytes in a 32-bit system.
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 * / / The sizeof operator says the size of the type of its argument. court <<"Size of char:" <<sizeof (c) <<" bytes "<<endl; court <<" Size of int: "<<sizeof (i) <<" bytes "<<endl; court <<" Size of double: "<<sizeof (d) <<" bytes " <<endl; court <<endl; court <<"Size of char *:" <<sizeof (cp) <<"bytes" <<endl; court <<"Size of int *:" <<sizeof (pi) <<"bytes" <<endl; court <<"* Size of double:" <<sizeof (pd) <<"bytes" <<endl; |
Using Pointers
After his statement, the contents of a pointer is a random value, waste of memory, like any variable. For it to be useful we need to assign something to it. As a pointer stores a memory address, we need to 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 ; & x = px; y ; & y = py; 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 "the address", because his name is "address".
What's left of the equality has to be able to keep exactly the same kind that are on the other side of equality. A pointer holds an address. So to assign an address to a pointer in this case, you must obtain 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 of yours, cause a compilation error. Fortunately!
Once you have a pointer pointing to a valid address, we can access the contents of that 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 "appointed by the content." Also be careful not to be confused with the symbol for arithmetic product. To avoid confusion, remember that huge table of precedence of operators , that you just spent the eye and dropped into oblivion. Here you will find that the operator of-reference takes precedence over the multiplication operator. Done that 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 ; bp = & 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) * (* bp); "Valor da Pegadinha: " << c << endl ; court <<"Value of Gotcha:" <<c <<endl; |
So when that proof of algorithms ask you what makes any one of the last five lines of the example, you will say that it multiplies the contents pointed by pa and pb. No more need to get DP for it! And breaking in real life, if you really need to do this, you will save your 4 generations past and future of 5 excommunication , if you choose to use the last line.
All you can do 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 rant ...).
Addresses and Pointers
Take 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 ("& ap =% p \ n", & pa), / / Address as valid by the OS. "&pb = %p \n " , & pb ) ; // Endereço válido dado pelo SO. printf ("& sc =% 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 ("sc =% p \ n", bp) / / Content uninitialized (random). / / Try uncommenting the following lines, recompile and run. / / Printf ("* pa =% d \ n", * pa) / / What is (random *)? / / Printf ("* bp =% d \ n", * bp) / / What is (random *)? " \n Após as inicializações dos ponteiros: \n " ) ; printf ("\ n After the initialization of pointers: \ n"); a ; pa = & a; b ; bp = & 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 ("& ap =% p \ n", & pa) / / Even valid address given by the OS. "&pb = %p \n " , & pb ) ; // Mesmo endereço válido dado pelo SO. printf ("& sc =% p \ n", & bp) / / Even 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 inicializado (&a). printf ("pa =% p \ n", pa) / / initialized Content (& a). "pb = %p \n " , pb ) ; // Conteúdo inicializado (&b). printf ("sc =% p \ n", bp) / / Content starts (& b). "*pa = %d \n " , * pa ) ; // Conteúdo apontado por pa (*pa == a). printf ("* pa =% d \ n", * pa) / / Content appointed by pa (pa == * a). "*pb = %d \n " , * pb ) ; // Conteúdo apontado por pb (*pb == b). printf ("* bp =% d \ n", * bp) / / pointed to by bp Content (* bp == b). " \n Após as inicializações dos inteiros: \n " ) ; printf ("\ n After the initialization of the 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 ("& ap =% p \ n", & pa) / / Even valid address given by the OS. "&pb = %p \n " , & pb ) ; // Mesmo endereço válido dado pelo SO. printf ("& sc =% p \ n", & bp) / / Even valid address given by the OS. " \n " ) ; printf ("\ n"); "a = %d \n " , a ) ; // Conteúdo inicializado (10). printf ("a =% d \ n", a) / / initialized Content (10). "b = %d \n " , b ) ; // Conteúdo inicializado (13). printf ("b =% d \ n", b) / / initialized Content (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 ("sc =% p \ n", bp) / / Content starts (& b). "*pa = %d \n " , * pa ) ; // Conteúdo apontado por pa (*pa == a == 10). printf ("* pa =% d \ n", * pa) / / Content ap pointed by (* ap == a == 10). "*pb = %d \n " , * pb ) ; // Conteúdo apontado por pb (*pb == b == 13). printf ("* bp =% d \ n", * bp) / / pointed to by bp Content (* bp == b == 13). " \n Alterando os valores através dos ponteiros: \n " ) ; printf ("\ n Changing values via 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 ("& ap =% p \ n", & pa) / / Even valid address given by the OS. "&pb = %p \n " , & pb ) ; // Mesmo endereço válido dado pelo SO. printf ("& sc =% p \ n", & bp) / / Even valid address given by the OS. " \n " ) ; printf ("\ n"); "a = %d \n " , a ) ; // Conteúdo inicializado (a == *pa == 7). printf ("a =% d \ n", a) / / initialized Content (* ap == a == 7). "b = %d \n " , b ) ; // Conteúdo inicializado (b == *pb == 42). printf ("b =% d \ n", b) / / initialized Content (* bp == b == 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 ("sc =% p \ n", bp) / / Content starts (& b). "*pa = %d \n " , * pa ) ; // Conteúdo apontado por pa ( 7). printf ("* pa =% d \ n", * pa) / / ap pointed by Content (7). "*pb = %d \n " , * pb ) ; // Conteúdo apontado por pb (42). printf ("* bp =% d \ n", * bp) / / content pointed to by bp (42). |
Lines 18:19 respectivamnete declare two integers and two pointers to integers.
Lines 23 to 26 show the addresses of my variables. These addresses were given by the operating system and while these variables are fixed there. A variable does not change address during program execution, but can change from one implementation to another. Who defines what is this address is the operating system at the time of program execution. The compiler only knows that x bytes are needed for each variable, and of the interpretation (type) that the program will give this space.
Lines 30 to 33 show the contents of these variables, which has not been initialized. It's garbage, the last value that someone (I do not know who) put those places in computer memory and which now belong to my variables.
Note that it is safe to uncomment lines 36 and 37 as they try to access the content pointed by pa and pb, which has not been initialized. During this attempt, the program will try to interpret those values of random junk like int variables 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 certain source of problems.
In lines 41 and 42 pointers are initialized with the addresses of integer variables a and b. From there the prints are repeated.
See the addresses of pointers that do not change, which was expected. What are its contents change. The 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 which were given by the OS at the beginning of the program. Check with the previous prints. The content pointed by pa and pb is the same content of a 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.
In lines 61 and 62 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 trash. Values are well known. Note that there is no change in the addressing of variables in relation to the previous steps, only the values.
See also that after a and b have been initialized, the contents pointed to by pa and pb are also changed automatically. This happens precisely because pa and pb 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 to 97 show that the converse is also true, ie, changing the contents pointed to by a pointer, automatically changes the contents of the original variables pointed out by them.
It is easier to understand this thinking of 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 4 posts, see references, differences and similarities 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
- http://blog.blabos.org/2009/05/ponteiros-e-referencias-em-c-parte-2/ pointers and references in C + + Part 2: Blog Blaber of bleb
- http://www.caloni.com.br/blog/archives/ultimas-pesquisas-na-blogosfera-nacional Caloni.com.br »Blog Archive» Latest research in the national blogosphere
- http://blog.blabos.org/2009/05/ponteiros-e-arrays/ Pointers and Arrays: Blaber Blog of bleb
- Fernando
- Fernando
- http://blabos.pip.verisignlabs.com/ blab
- http://blabos.pip.verisignlabs.com/ blab
- Bruno http://www.brunodanielmarinho.com
- Bruno http://www.brunodanielmarinho.com

