Pointers in C
Address in memory
Before going deep into the pointers. Let us understand the operator &.
Create an address.c file and write a small program.
#include <stdio.h>
int main() {
int a;
printf("Address of variable a in memory is: %u\n", &a);
int b;
printf("Address of variable b in memory is: %u\n", &b);
double c;
printf("Address of variable c in memory is: %u\n", &c);
int d;
printf("Address of variable d in memory is: %u\n", &d);
return 0;
}
andrey@olegovich:/mnt/c/Users/Andrei/c$ gcc -o address address.c
andrey@olegovich:/mnt/c/Users/Andrei/c$ ./address
Address of variable a in memory is: 3802827836 Address of variable b in memory is: 3802827832 Address of variable c in memory is: 3802827824 Address of variable d in memory is: 3802827820
As you can see, we got the address a and the address b, which is less by four, the address c is less by 8 because type c. Double and it needs not 4 but 8 bytes. With this method, you can check exactly how much byte takes up. One or another type of compiler.
Introduction to pointers
Pointers store variable addresses in memory. Although this is not a real address in your CPU but a virtual one, later mapped to the real one by your OS, that does not change the essence.
The pointer is also a variable, so you can make a pointer to the pointer.
Pointers have a type. This is very important because each type stands out.
A certain amount of memory.
char * ptr_to_char;
However, you can specify the void pointer (i.e. with an unknown type).
void * ptr_to_unknown;
You should be especially careful with such pointers.
A pointer = 0 is a null pointer, a pointer that does not point anywhere.
int * ptr_to_nothing = 0;
If your pointer points where it should not, you will get segmentation fault.
Dereferencing means getting the value stored where the pointer points.
Let us consider a small example.
#include <stdio.h>
#include <stdlib.h>
int main() {
int money = 100;
int *p = &money; // p points to a memory location,
// in which variable money is stored
// The current value stored there is 100.
printf("money = %d\n", money); // Expect to see 100
printf("p = %d\n", p); // Expect to see the address of the variable money
// dereferencing
printf("*p = %d\n", *p); // Expect to see 100
int balance;
// dereferencing
balance = *p + 20;
printf("balance = %d\n", balance);
return 0;
}
Run this code twice in a row.
andrey@olegovich:/mnt/c/Users/Andrei/c$ ./money
money = 100 p = -814504480 *p = 100 balance = 120
andrey@olegovich:/mnt/c/Users/Andrei/c$ ./money
money = 100 p = -691897248 *p = 100 balance = 120
money and balance, as expected, do not change, but the address the memory allocated for money, which we observe through p changes
#include <stdio.h>
int main() {
int a;
printf("Address of variable a in memory is: %u\n", &a);
// We are expecting an unknown number.
int b = 10;
printf("Address of variable b in memory is: %u\n", &b);
// Expect a number 4 less than the previous one
double d;
printf("Address of variable d in memory is: %u\n", &d);
// Expect a number 8 less than the previous one
float f = 5.8;
printf("Address of variable f in memory is: %u\n", &f);
// Expect a number 4 less than the previous one
int *ptr1;
ptr1 = &a;
int *ptr2 = &b;
float *ptr3 = &f;
printf("---------------------------------------------------\n");
printf("Value of ptr1 is %u\n", ptr1); // Expect address a
printf("Value of ptr2 is %u\n", ptr2); // Expect address b
printf("Value of ptr3 is %u\n", ptr3); // Expect address f
printf("---------------------------------------------------\n");
printf("Value stored in a = %u\n", a); // Expect some garbage
printf("Value stored in a access with ptr1 = %u\n", *ptr1); // Expect the same junk value
printf("Value stored in b = %u\n", b); // Expect 10.
printf("Value stored in b access with ptr2 = %u\n", *ptr2); // Expect 10.
printf("---------------------------------------------------\n");
printf("Comment: now a = 30 \n");
printf("---------------------------------------------------\n");
a = 30;
printf("Address of variable a in memory is: %u\n", &a); // Expect the same address
printf("Value stored in a = %u\n", a); // Expect 30.
printf("The sum of a and b is %d\n", *ptr1 + *ptr2); // Expect 40.
printf("---------------------------------------------------\n");
printf("Address of ptr1 in memory is: %u\n", &ptr1);
// We are expecting an unknown number.
printf("Address of ptr2 in memory is: %u\n", &ptr2);
// Expect a number 8 less than the previous one if you have x64 architecture and 4 less if x86
printf("Address of ptr3 in memory is: %u\n", &ptr3);
// Expect a number 8 less than the previous one if you have x64 architecture and 4 less if x86
printf("---------------------------------------------------\n");
printf("Comment: now ptr1 = ptr2\n");
printf("---------------------------------------------------\n");
ptr1 = ptr2; // now ptr1 points in the same direction as ptr2
printf("Address of variable b in memory is: %u\n", &b);
// Address b must not change from previous call
printf("Value of ptr1 is: %u\n", ptr1); // Expect address b
printf("Value stored in b access with ptr1 = %u\n", *ptr1); // Expect 10.
printf("---------------------------------------------------\n");
printf("Address of ptr1 in memory is: %u\n", &ptr1); // Address ptr1 should not change
printf("Address of ptr2 in memory is: %u\n", &ptr2); // Address ptr2 should not change
printf("Value stored in a = %u\n", a); // Expect 30.
printf("---------------------------------------------------\n");
return 0;
}
An example from wikipedia.org
int n = 6; // Declaring a variable n type int and assigning it a value of 6
int *pn = malloc( sizeof ( int ) ); // Declaring the pn pointer and allocating memory for it
*pn = 5; // Dereferencing the pointer and assigning the value 5
n = *pn; Assigning to n the value (5) that pn points to
free(pn); // Release of occupied memory
pn = &n; // Assigning a variable n address to pn (the pointer will refer to n)
n = 7; // *pn is also 7.
How to cause a segmentation fault
It's easy - try dereferencing a pointer that points nowhere.
#include <stdio.h>
#include <stdlib.h>
int main() {
int * p = 0;
int var = *p + 3;
return 0;
}
Article author: Andrei Olegovich
| C development | |
| Textbook on C | |
| Boolean in C | |
| Sockets in C | |
| K&R | |
| What is argc, char * argv[] | |
| Function scanf() | |
| Pointers | |
| Structures in C | |
| Operator «arrow» pointer to member structure |