Pointers. Part 2. Unmanaged pointers. Operations on pointers. Pointer to type void. Memory allocation. Keywords NULL and nullptr. The operation of getting the address &
This topic describes how to work with unmanaged pointers. As you know, Visual C++ also supports managed pointers.
General information about the pointers, types of pointers are detailed in the topic here.
Contents
- 1. Which operators can be used with unmanaged pointers?
- 2. What is an indirect access operation with a pointer?
- 3. How does the C++ compiler determine the amount of information that the pointer points to?
- 4. The operation of assigning pointers. Example
- 5. Arithmetic operations on pointers. Changing the physical address of the pointer. Examples
- 6. What kind of relation operations (comparisons) can be performed with pointers?
- 7. What are the features of using a pointer to a void type?
- 8. How set the pointer to zero value? Keywords NULL and nullptr. Examples
- 9. An example of allocating the memory by the function malloc(), which returns a pointer to the type void
- 10. What restrictions are imposed on the operation of taking the address &?
- 11. Is it possible set the pointer to a physical memory address directly?
- Related topics
Search other websites:
1. Which operators can be used with unmanaged pointers?
Over unmanaged pointers two operators are used:
- * – is intended for accessing a variable, which is located at the address, which is specified by the operand of this operator. This operator refers to the value of the variable, which is recorded in the pointer. This is a unary operator, in which the operand is placed on the right;
- & – returns the memory address of the operand located on the right. This is a unary operator.
Operators * and & complement each other.
For example. A pointer named px refers to a variable x of a real type. Suppose that we have the following description:
float x; float *px; // Pointer to a variable of real type px = &x; // px points to x
The value *px is the value of the variable x, which is shown by the following line
*px = 25; // x = 25.0
The value of px is the address of the variable x in the RAM.
Figure 1. Pointer px points to the variable x
2. What is an indirect access operation with a pointer?
The indirect access operation is access to a variable (object) using a pointer. Using the pointer, you can access arrays of variables (objects).
The word “indirect” means that you can access the value of a variable using another variable.
3. How does the C++ compiler determine the amount of information that the pointer points to?
The amount of information processed is determined by the base type of the pointer.
Example. Let the following description be given:
double * pf;
The basic type of the pointer is double. One variable of type double occupies 8 bytes in the computer’s memory. Therefore, the C++ compiler will process 8 bytes of information when accessed by the pointer.
4. The operation of assigning pointers. Example
The value of one pointer can be assigned to another, provided that they have the same base type (they are pointers to the same data type).
If pointers point to different types of data, then the type cast operation operates. In this case, working with the pointer is unpredictable and can lead to invisible logical errors (or maybe not).
Example.
// assignment of pointers int a = 5; // ordinary variable int * pi1 = &a; // Initializing the pointer with the address of variable a int * pi2; // pointer to int double * pi3; // pointer to double pi2 = pi1; // acceptably //pi3 = pi1; // error! - "cannot convert from int to double" pi3 = (double *) pi1; // it works - the type cast operation
5. Arithmetic operations on pointers. Changing the physical address of the pointer. Examples
You can perform the following arithmetic operations with pointers:
- increment ++ and decrement — operations;
- addition + and subtraction – operations.
Pointers can be used in expressions.
When changing pointer values using arithmetic operations, physical address of pointer is changed by the formula:
N * sizeof(type)
where
- N – a constant that indicates the change (increase / decrease) in the value of the pointer;
- type – The type of data pointed to by the pointer (the base type of the pointer);
- sizeof(type) – an operation that determines the size of the data type.
Example 1. Changing the pointer value.
// increasing / decreasing the pointer value int a = 5; // ordinary variable int * pi1 = &a; // Initializing the pointer with the address of variable a int * pi2; // pointer to int pi2 = pi1; // point to the same memory address pi2++; // physical address of pi2 is 4 bytes greater than the address pi1
In the above example, the physical address of pointer pi2 is more by 4 bytes from the physical address of pointer pi1. This is due to the fact that int (the basic type of pointers pi1 and pi2) is 4 bytes in size (Win32 environment).
Example 2. Changing the value of a pointer to type double.
// increasing / decreasing the pointer value double x = 3.55; // ordinary variable of type double double * p1 = &x; // initializing the pointer with the address of variable a double * p2; // pointer to double p2 = p1-4; // the physical address p2 is 32 bytes smaller than the address p1 p2 = p1 + 2; // the physical address p2 is 16 bytes greater than the address p1
6. What kind of relation operations (comparisons) can be performed with pointers?
Pointers can be compared. For comparing pointers, the operations ==,>, < are used.
When comparing pointers, it is important that these pointers have some connection with each other.
For example, if pointers point to different unrelated variables, then the comparison operation does not make sense.
In the event that pointers point to variables between which there is some relationship, the result of the comparison makes sense. This can be the case where pointers point to elements of the same array.
Example. Let the array of real numbers A and 2 of the pointer be given.
// Comparison of pointers float A[20]; // array of 20 real numbers float *pa1, *pa2; // two pointers to "float" bool f_res; // Result of pointers comparison // ... pa1 = &A[5]; // Points to the 5th element of the array pa2 = &A[8]; // Points to the 8th element of the array f_res = pa1==pa2; // f_res = false f_res = pa1>pa2; // f_res = false f_res = pa1<pa2; // f_res = true
7. What are the features of using a pointer to a void type?
C++ allows you to use a pointer to void type. The pointer to type void has its own peculiarities. This means that a pointer to type void is a universal pointer that can be set to any type of value, including zero. The keyword void gives information for the compiler that there is no data about the size of the object in memory.
To set the void pointer to a pointer of another type, you need to use the cast operation.
Example. Using a pointer to type void to access variables of different types.
// pointer to 'void' type void * p; int d; float x; char c; d = 5; x = 2.58f; c = 'A'; p = (int *)&d; // p points to d *(int *)p = 8; // d = 8 p = (float *)&x; // p points to x *(float *)p = -8.75; // x = -8.75 p = (char *)&c; // p points to c *(char *)p = 'r'; // c = 'r'
8. How set the pointer to zero value? Keywords NULL and nullptr. Example
There are cases when a pointer needs to be set to zero. This is necessary to set the value of the pointer to something that does not match any of the pointers that are used in the program.
In the <stdio.h> module, a NULL constant with a zero value is defined. It can be used to assign a null value to a pointer.
You can also use the nullptr pointer to set a null pointer, which is less vulnerable to misuse and performs better in most cases (see example 2).
Example. Assigning a zero value to a pointer.
#include <stdio.h> ... // null pointer int * p; p = nullptr; // Works p = NULL; // Works, the constant NULL is defined in the module <stdio.h> p = 0; // it works p = 0x00; // also works
Example 2. A case where it’s better to use nullptr instead of NULL.
#include <iostream> using namespace std; void func(std::pair<const char*, double> pr) { // ... } void main() { // Doesn't work - compilation error //func(make_pair(NULL, 3.14)); // NULL => 0 => int // Works func(make_pair(nullptr, 3.14)); // nullptr => nullptr_t => const char* }
In the example above, a NULL pointer is converted to the number 0, which is of type int by default. And in our case, it is necessary that the type be const char*. When using the nullptr pointer, this error will not occur.
9. An example of allocating the memory by the function malloc(), which returns a pointer to the type void.
The malloc() function allocates memory for an unmanaged pointer. Function returns a void* type.
To assign to the pointer a value of the memory address allocated to the object , you must perform an explicit type cast.
Example. Using the malloc() function.
// example of allocating memory to an unmanaged pointer int * p; p = NULL; // allocating the memory by the malloc() function for a pointer to an int p = (int *)malloc(sizeof(int)); // Allocating memory using the malloc() function for a pointer to double double * pd = NULL; pd = (double *)malloc(sizeof(double));
10. What restrictions are imposed on the operation of taking the address &?
The following restrictions are imposed on the operation of taking the address &:
1. It is impossible to determine the address of the constants. For example, expression
pi = &0xffe800;
will generate an error.
2. It is not possible to determine the address of the value that is obtained when calculating the expression. For example, a code snippet
int *pi; int d; d = 8; pi = &(d + 5); // Error, can not get the address of the expression
will result in an error.
11. Is it possible set the pointer to a physical memory address directly?
The Visual C++ compiler allows the pointer to be set a direct memory address. However, when accessing this address, a critical situation occurs with the error message:
"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
This means that an attempt was made to access the protected memory. This applies to both console applications and applications created using the Windows Forms Application template.
Example. Assignment of the physical address to the pointer.
// Assignment of the physical address to the pointer. float *pf; // pointer to float float f; // ... // assignment of the physical address of memory (random value) pf = (float *)0xffff00; // it works f = (float)(*pf); // error! A critical situation arises
Related topics
- Pointers. Part 1. General concepts. Pointer types. Managed and unmanaged pointers. Pointers to a function. Examples of the use of pointers
- Pointers. Part 3. Unmanaged pointers and arrays. Pointer to structure. Pointer to class
- Pointers. Part 4. Pointers and strings. Using pointers when converting strings
- Pointers. Part 5. Memory allocation for the pointer. Arrays of pointers to basic types, functions, structures, classes
- Pointers. Part 6. Composite managed and native data types. Managed pointers (^) in CLR. Memory allocation. The ref and value qualifiers. Managed pointers to structures and classes
- Arrays. Part 1. Array definition. One-dimensional arrays. Initializing array
- Arrays. Part 2. Two-dimensional arrays. Arrays of strings. Multidimensional arrays
- Based types in C++ (Visual C++)