[C/C ++ language entry]-array and pointer

Source: Internet
Author: User

We have introduced pointers in the previous article. I believe that pointers are no longer so unfamiliar, although some readers are not used to the bold forced type conversion of pointers. But at least everyone has a number in mind, and the pointer is so flexible that you can operate at a lower level or simply go beyond some syntax restrictions. This may also be one of the reasons why many programmers have attacked CC ++ for being insecure. Security is not what we want to express in this article. Here we only need to remember that if you are sure you can use it without hesitation.

 

This article still does not leave the pointer shadow. The previous article has not been fully described. I would like to introduce it in the previous article, but I found that this article is more suitable. Arrays and pointers can be said to be two relatives. Many beginners have ambiguous concepts about the two. What are the links and differences between them is what many beginners want to understand most. This article aims to solve this problem and further deepen the pointer and array. Remember our starting point and understand Lenovo with divergent thinking. Focus on the process of thinking. In the end, this process only needs to be expressed by a program.

 

First, let's look at what an array is. An array is a continuous space (memory space ). From this sentence, we can note that the array is actually a piece of space and continuous. Now we have a general understanding of the basic features of the array. How is the memory space expressed? Simple:

Int A [100];

Char szname [16];

 

These two sentences are arrays. Here, A is an array with 100 int elements. Here we can also understand that int is not the type of array A, but the type of elements inside the array. It indicates that each element in the array is a 32 signed integer. In this case, the pointer is connected. int * P; P indicates that the data stored in the memory address it points to is int type. The second szname also indicates that the type of each element is Char. This understanding is helpful for pointer arrays and array pointers. Here we will introduce them first.

 

Here, a and szname are not initialized, so the values of each element in them can be considered as garbled characters. That is to say, some values are randomly filled. Of course, it makes sense to fill these values. The values may be different on different platforms. In Windows, it is usually filled with something like 0xcdcdcd or 0xcccccccc. These values will be more straightforward to understand at the Assembly level. Here we will think that they are some of the values that can be filled casually. These values are considered useless to our normal program.

 

From the perspective of program performance, we already know the declaration of arrays. How can we connect with pointers and make a difference? Post Code first:

Int * P = A; // here, a uses the array a [100] above.

We can only know from the previous article that the pointer P points to the first address of array A, where A is directly assigned to P. It can be concluded that the array name a represents the first address of the array. Since it represents the first address, A can be considered as a memory address pointing to the first element of the 100 int type. CC ++ directly specifies that the array name will be the pointer to the first address of the array:

Element 1 <----

Element 2

Element 3

Element 4

...

Therefore, assigning a value directly to P is completely legal and feasible. Of course, we can also avoid using this rule:

Int * P = & A [0];

In this way, you can obtain the first address of the array, that is, the memory address of the first element.

 

Here, we should think about it. In essence, an array is a continuous memory space, even if there is only one element, it is also an array, because these elements are placed in the memory, it certainly has its own memory address, once the memory address is involved, it can point to it with a pointer. Therefore, the pointer is connected. Why should we treat the array name as a pointer? In fact, the array name is not the same as the pointer, because the array name also has more information than the pointer, for example:

Int array [10];

Int size_a = sizeof (array );

 

Int * parray = array;

Int size_p = sizeof (parray );

From the two codes, we should know that the values of size_a and size_ B are 40 and 4 respectively. The difference here is obvious. If array is regarded as a pointer, size_a should be 4 characters long. In the previous article, we introduced that pointer variables are a 32-bit unsigned integer. Therefore, the pointer length in a 32-bit platform can be directly considered as 4. Why is the number of bytes of 10 elements? The reason is very simple. when processing the array name, the compiler will know how much space the array declares and will find out how many bytes of memory the array actually occupies. When we assign the first address of the array to the parray pointer, parray will lose the size of the array. This loss is evident in function parameters, for example. Let's talk about functions later. The compiler will not go into the root cause or investigate what is assigned. Therefore, it is not accurate to say that the array name is exactly the same as the pointer. In essence, it can be said that it is equivalent to the first address of the stored array.

 

In the previous pointer articles, we did not talk about pointer ++ and -- operations. Here we will describe it with arrays. The accumulation or subtraction of pointers is also related to the type, for example:

Int * P = A; // A is a [100]

P ++;

P --;

 

Here, the sum and subtraction are related to the type. By observing or conjecture, we can know that the memory address value saved after P is accumulated once is 4 bytes backward. Because the type is int. Here P points to the address of the first element of array A. After accumulation, it points to the first element. The interval is 4 bytes. The subtraction is also an interval of 4 bytes. Similar:

Int * P = A; // A is a [100]

P = P + 2;

P = p + 1;

These do not use the accumulate operation, but also calculate the actual number of bytes of the address based on the type. Here, + 1 is equivalent to adding 4 to the address, and + 2 is equal to adding 8. If it is another type, such as the struct type, or the actual address, the size of the Skip struct is multiple bytes. I will explain the struct in the future.

Question 1: What is the value of int Dis = & A [0]-& A [1]; dis? Why?

 

From the feature of accumulate and accumulate, we can guess that at the beginning of the design pointer, we should consider the pointer pointing to the array feature, so accumulate and accumulate become the feature of accessing an element in the array. Therefore, to access an element of a, we can use:

P [0] P [1]... P [N. Of course, you must grasp the size of the array with pointer operations, otherwise the read and write operations will be out of bounds. The consequences are very serious.

 

Here we have another point worth comparing and associating, such as the Code:

Int A [100];

A ++;

(Int *) a) ++;

Int Var = A [0];

Question 2: Are the above two codes valid? Can we determine the differences between array names and pointers?

 

Int * P = A; // A [100]

Question 3: What is the difference between * P ++ and (* P) ++?

 

From every detail shown above, we should get used to thinking. Summarize the real connections and differences between the two things. I believe this is good for you.

 

Next, let's talk about pointer arrays. A pointer array stores all pointers in an array. In essence, all elements are memory addresses. That is, a 32-bit unsigned integer. It can be regarded as an unsigned int array.

Int main (void)
{
Int A [10];
Int * AP [10];
Int I;

 

For (I = 0; I <10; ++ I)
{
AP [I] = & A [I];
}

 

Return 0;
}

 

In the above Code, AP is a pointer array, and each element type is the memory address of the int type data (it can be said: int type pointer ). Then, a loop copies the memory address of all elements of array a to each element of the pointer array. array A does not have the element value even though it is not initialized, however, once declared, the array has allocated memory space. Here is the partial array in the stack space. Therefore, it is absolutely legal to obtain the address of each element of a in a loop. The AP is not initialized when it is declared, and the initial values of each pointer element in it are also messy like ordinary arrays. Suppose we have this operation before the loop:

Int a_var = * (AP [0]); // This sentence aims to remove the data pointed to by the AP's 0th elements (pointers. No parentheses are provided here.

In this case, the pointer is not initialized. If it is initialized, but it is initialized to an invalid memory address, indirect access is quite dangerous.

The above loop assigns the addresses of each element of array A to the corresponding elements of the AP. So:

Int * P = A; // A [100]

Each time P accumulates 1, p Stores the memory address, which can accurately correspond to the value (memory address) of each element in the AP ). This also illustrates the relationship between arrays and pointers. Here we can summarize:

If the pointer points to a valid continuous space, this pointer can be seen in the same way as an array. You only need to pay attention to the upper and lower limits. You can also think that any pointer that is randomly assigned (pointing to) any memory address can be accessed with array subscript or accumulated and then indirectly accessed, as long as this memory you need and are valid.

 

Let's look at The Void pointer mentioned above.

Void * PPP = (void *) A; // A [100]
PPP ++;

Question 4: Is this sentence legal? Why? (This is explained in the previous article)

 

Finally, let's look at the array pointer, or the code first:

Int main (void)
{
Int A [2] [10];
INT (* P) [10]; // array pointer

P =;
P = & A [0];
P = A [1];

Return 0;
}

 

In the above program, P is an array pointer. As the name implies, this pointer stores an array. From this point of view, this pointer points to the first address of the array. P indicates an integer array with 10 elements. 10 in brackets indicates that the array to which it points is 10 elements. Here we define a two-dimensional array A, P = A; and then assign a value to P. Let's think about its memory relationship.

A [0]: {A [0] [1], a [0] [1],..., a [0] [9]} <------ P [0]

A [1]: {A [1] [1], a [1] [1],..., a [1] [9]} <------ P [1]

Therefore, the memory relationship between P and A is clear. P points to a one-dimensional array, which is a two-dimensional array. A two-dimensional array can be regarded as several rows and several columns. Each row is a one-dimensional array. P can be called a row pointer. You should understand it! Then, P ++ will jump to a row of so many bytes. Here, a row contains 10 int elements, which is 40 bytes. You can write a program and observe it by yourself. P = & A [0]; that is, the 1st rows of the Two-dimensional array are assigned to P. Similarly, you can assign the first row to P, P = & A [1]; thus, P is a row pointer.

Question 5: Is this statement valid in the above program: P = A [1? Why?

 

Some readers may raise another question: is there a pointer to a two-dimensional array? As you can imagine in space, if you point to a two-dimensional array, the accumulation of pointers will increase the thickness of the cube (3D space, 3D array ). Just like the sandwich we eat, one of the three pieces represents our two-dimensional array pointer. We will not discuss it here.

 

 

Here, we also need to explain the relationship and difference between the second-level pointer and the two-dimensional array. The same difference between pointer and array name has been mentioned earlier. Here we only look at the access value and memory relationship after the two-dimensional array to the second-level pointer.

If you try:

Int A [2] [10];
Int ** P = (INT **);

This will cause a disaster. The syntax is correct. Originally, our array A contains integers, which are forcibly converted into pointers. P [0] is the value of the first element in the first line of, then P [0] [0] is the value where P [0] is stored as the memory address. Therefore, unless your A [0] [0] is your data, your use of this will have devastating consequences-crash. However, here P [0] gives us an inspiration. We can write another code:

Int main (void)
{
Char * AP [3] = {"hello", "happy", "good "};
Char ** app1 = ap;

Return 0;
}

A pointer array AP is defined here and then converted to a char ** second-level pointer. We can see the relationship through subscript operations.

AP can also be regarded as a two-dimensional array with three rows and six columns. Therefore:

The value of AP [0] [0] Is 'H.

The value of APP [0] [0] is also 'H.

I believe you have understood the differences and relationships between two-dimensional arrays and second-level pointers.

Convert a two-dimensional array directly to a second-level pointer. This will cause a problem because of this conversion. When you use the second-level pointer subscript to access the first row of data, the address of the first element in the first row is considered as the currently stored value as the next-level pointer value (address ). That is to say:

Char AP [3] [6] = {"hello", "happy", "good "};
Char ** app1 = (char **) AP;

Then, app1 [0] (that is, * app1, * (* app1) indicates app1 [0] [0]) value (memory address) the first 4 bytes of the "hello" string "hell" are converted into the ASCII code: 0x6c6c6568.

68 65 6C 6c

H e l

As for why 0x6c6c6568 is reversed, it is because my CPU is a small-end storage, the high bytes are considered as the high integer, and the low bytes are considered as the low integer. Now we know the relationship between two-dimensional arrays and second-level pointers.

 

The example here is a char array. You can also use an int array. I will not write it here!

Well, this article is here! It has been written for more than four hours. It is already the next day.

The questions mentioned above are worth the consideration of beginners. Come on!

 

[C/C ++ entry series]

[C/C ++ language entry] -- Preface

[C/C ++ language entry] -- Thinking about helloworld

[C/C ++ language entry] -- Basic Data Type

[C/C ++ language entry]-debugging Basics

[C/C ++ language entry]-deep pointer

[C/C ++ Introduction] -- array and pointer

[C/C ++ Introduction] -- Structure

[C/C ++ language entry] -- go deep into Functions

[C/C ++ language entry]-bit operations

[C/C ++ language entry] -- analyzes floating point numbers

[C/C ++ language entry] -- File Operations

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.