Learn more about c++ arrays and Pointers

  • 2020-11-03 22:32:31
  • OfStack

An array of 1.

Array size (number of elements) is usually determined at compile time, but a few compilers can dynamically determine array size at run time, such as icpc (Intel C++ compiler).

1.1 The meaning of array names

The essence of an array name is a literal constant that represents the address of the first element of the array and the first address of the array. Array names are not themselves a variable, cannot be addressed, and are not allowed to assign values to array names. Suppose an array is defined:


int A[10];

Then define another reference:


int* &r=A;

This is an error because the variable A is a literal constant and cannot be addressed. If you want to make a reference to the array A, you should define it like this:


int* const &r=A;

At this point, an anonymous temporary variable is now created in the data area. The address constant represented by the array A is copied into this variable, and the frequent reference r is bound to this variable. In addition, if an array A is defined, then A, & A[0] and A+0 are equivalent.

In the sizeof() operation, the array name represents all array elements, not a single element. For example, int A[5] is defined to generate Win32, sizeof(A) is equal to 5*sizeof(int)=5*4=20. The sample program is shown below.


#include <iostream>
using namespace std;

int main()
{
int A[4]={1,2,3,4};
int B[4]={5,6,7,8};
int (&rA)[4]=A; // Build array A A reference to the 

cout<<"A:"<<A<<endl;
cout<<"&A:"<<&A<<endl;
cout<<"A+1:"<<A+1<<endl;
cout<<"&A+1:"<<&A+1<<endl;
cout<<"B:"<<B<<endl;
cout<<"rA:"<<rA<<endl;
cout<<"&rA:"<<&rA<<endl;
}

Operation results:

[

A:0013F76C
& A:0013F76C
A+1:0013F770
& A+1:0013F77C
B:0013F754
rA:0013F76C
& rA:0013F76C

]

Read the above program and note the following points.

(1) A and & The result of A is numerically 1, but A and & The A data type is different. The type of A is int[4], & The type of A is int(*)[4]. They are conceptually different, which leads directly to A+1 and & The result of A+1 is completely different.

(2) type is the syntax format for establishing references to variables & ref, because the array A is of type int[4], the reference established for A is int ( & rA)[4]=A;

1.2 Array initialization

When you define an array, assigning an initial value to an array element is called array initialization. You can specify an initial value for a 1-dimensional array or a multidimensional array. For example.


Int A[5]={}; // Define length as 5 The values of all the elements of the array are 0
int A[]={1,2,3}; // Define length as 3 The elements of the array are 1,2,3
int A[5]={1,2}; // Define length as 5 The array, A[0] . A[1] Respectively, 1,2 , the other values are 0
int A[][2]={{1,2},{3,4},{5,6}}; // define 1 A type of int[3][2] the 2 Dimensional array 
int A[][2]={{1},{1},{1}}; // define 1 A type of int[3][2] the 2 Dimensional array, A[0][0] , A[1][0] , A[2][0]3 The values of the elements are 1 , the values of all other elements are 0

// Here are a few incorrect initializations 
int A[3]={1,2,3,4}; // The number of initializers exceeds the length of the array  
int A[3]={1,,3}; // Skipping an item in between is not allowed 

Pointer to 2.

2.1 Definition of Pointers

A pointer is a variable that holds an address value, and the corresponding data type is called a pointer type. On a 32-bit platform, any pointer type takes up 4 bytes of space. For example, sizeof(int*), sizeof(double*), sizeof(float*), etc., all have a value of 4.

2.2 Define the form of Pointers

The pointer is defined as type* p, where type is the data type of the object to which the pointer points, * is the flag of the pointer, and p is the name of the pointer variable. Because the definition of composite data types is allowed in C++, the way Pointers to composite data type objects are defined can be complex. The key to understanding Pointers is to understand the type of pointer and the type of data that the pointer points to. Such as:


int (*p)[5]; // Pointer to the p Is of type int(*)[5] , the data type to which the pointer points is int[5]
int* p[5]; //p There is a 5 An array of Pointers to three components, each of type int* (pointing to int The pointer) 
int** p; // Pointer to the p Is of type int** . p The type of the point is int* . p It's a pointer to a pointer 

2.3 Initialization of Pointers

When a pointer variable is defined, the value 1 of the pointer variable is usually a random value, and such a value is not a legally accessible address. There are usually two ways to decriminalize the value of pointer variables,
1 is a display null, 2 is a pointer to an existing variable, and 3 is a dynamic memory space request for the pointer. As follows:


// According to empty 
int *p=NULL;

// Points a pointer to a variable 
int i;
int *p=&i;

// Dynamically request memory space 
int* p=new int[10];

2.4 Operations that Pointers can participate in

Since a pointer is a variable, a pointer can participate in some operations of 1. Suppose the pointer int* p is defined, and the operation that the pointer p can participate in is:
(1) De-reference operation, that is, to obtain the data at the memory address indicated by the pointer, the expression is *p. If the pointer points to an object of a structure or class, then there are two ways to access object members: *p.mem or p- > mem.

(2) Get the address operation, that is, get the address of pointer variable, the expression is & p, whose data type is int**;

(3) Pointer and integer plus or minus. The expression p+i (or ES146en-ES147en) actually moves the pointer increments or decrements the distance between i's int variables.

(4) When two Pointers are subtracted, such as p-q, the result is the number of int data between the addresses stored by the two Pointers.

2.5 Pay attention to the validity of Pointers

The key to using a pointer is to have the pointer variable point to a memory address that it can legally access. If you don't know where it points, set it to null NULL or ((void*)0).

In some cases, the value of the pointer starts out legal, and later becomes illegal as some operations proceed. Consider the following procedure.


#include <iostream>
using namespace std;

int* pPointer;
void SomeFunction()
{
int nNumber=25;
pPointer=&nNumber; // The pointer pPointer Point to the nNumber
}

void UseStack()
{
int arr[100]={};
}

int main()
{
SomeFunction();
UseStack();
cout<<"value of *pPointer:"<<*pPointer<<endl;
}

The output is 0, not 25. The reason is that the local variable nNumber has been emptied after the function SomeFunction() has finished running, and the space it occupies is returned to the system after leaving the function, and then allocated to the local variable arr in the function UseStack(). So the dereferenced value of the pointer pNumber becomes 0. Therefore, in order to use the pointer correctly, it is necessary to ensure the validity of the pointer to the unit.

3. Array and pointer relationship

The array name represents the first address of the array, and A[i], an element of the array A, can be interpreted as *(A+i), so the array name itself can be interpreted as 1 pointer (address), 1 pointer constant. So, in many cases, arrays and Pointers are used in the same way, but there are some important differences between arrays and Pointers in nature.

(1) Array space is allocated statically, and its size is determined at compile time. When the pointer is defined, there is no valid access to the address space, that is, wild pointer.

(2) The array name represents a pointer constant, and any attempt to change the address represented by the array name is illegal. For example, the following code:


int arr[5]={0,1,2,3,4};
arr++; // Compile error 

(3) Arrays in function parameters are interpreted as Pointers. Examine the following procedures:


void show0(int A[])
{
A++;
cout<<A[0]<<endl;
}

void show1(int A[5])
{
A++;
cout<<A[0]<<endl;
}

int main()
{
int d[5]={1,2,3,4,5};
show0(d);
show1(d);
}

The above program compiled through and output 2 and 2. In the program, the form parameter group A can carry out self-increment operation, changing its own value, which indicates that the form parameter group A is treated as a pointer. There are two reasons for this. 1 is that C++ language does not check the subscript of array for overbounds, so the length of the shape parameter group can be ignored. 2 is when the array is passed as a whole, there will be a large runtime overhead. In order to improve the running efficiency of the program, the array is degraded into Pointers.

(4) If the function's parameter is an array reference, then the length of the array will be treated as part 1 of the type. In fact, to make a reference to an array is to make a constant reference to the first address of the array. Because references are a new mechanism introduced by C++, 1 specification different from the traditional C language is used in the handling of references. In the traditional C language, the subscript of an array is not checked for bounds, so both int[5] and int[6] are understood as int[] (i.e. int*) in the argument description of the function, and C++ follows this approach. However, int ( & ) [5] and int ( & )[6], which are considered as different data types, are strictly checked in the matching process of real participation parameters. Consider the following procedure.


int* &r=A;
0

Program results:

[

type is int( & )[5]

]

(5) Conceptually, Pointers correspond to 1-dimensional arrays. Multidimensional arrays are stored in a continuous storage space, and multidimensional arrays can be decomposed in different ways when viewed as 1-dimensional data. Consider the following procedure.


int* &r=A;
1

The program results show that the data results of the following three output statements are the same.


int* &r=A;
2

Their outputs are exactly the same, from 0 to 59. This means that the three dimensional array d can be treated as a one dimensional array in at least three different ways:

a. The data type is int, and the number of elements is 3*4*5=60;
b. The data type is int[5], and the number of elements is 3*4=12.
c. The data type is int[4][5], and the number of elements is 3.

So, think of multidimensional arrays as "arrays of arrays." When converting multiple arrays to Pointers, 1 must pay attention to the decomposition of multiple arrays in order to perform the correct type conversion.

(6) The difference between character array and character pointer.
Character array character Pointers are similar in form, but there are significant differences in memory space allocation and usage. As mentioned earlier, the array name is not a running entity and cannot itself be addressed. A pointer is a variable (a run-time entity) that can be addressed, and whether it points to a valid space is determined at run time. Using Pointers incorrectly will result in unauthorized access to the memory space. Consider the following procedure.


#include <iostream>
using namespace std;
int main()
{
char s[]="abc"; //s Is an array of characters, space allocated on the stack. Modifications to character array elements are legal 
char *p="abc"; 
s[0]='x';
cout<<s<<endl;
//p[0]='x'; // A pointer to a string in the constant region. Modifying a string constant is illegal 
cout<<p<<endl;
}

Program output results:

[

xbc
abc

]

The above is an in-depth understanding of c++ arrays and Pointers details, more c++ arrays and Pointers information please pay attention to other related articles on this site!


Related articles: