Do pointers and arrays of pointers and arrays be the same?
You can often see the phrase "array is pointer", "array name is constant pointer", but is that true? Let's take a look at the pointer and array definitions first.
1. Pointers
According to the C99 standard, pointers are defined as follows:
A pointer type describes an object whose value provides A reference to an entity of the referenced type. A pointer type derived from the referenced type T was sometimes called "pointer to T". The construction of a pointer type from a referenced type is called "pointer type derivation".
A pointer is a derived type that describes an object whose value is a reference to a type entity. It contains two meanings: the entity and the type.
It is important to note that pointer variables are just a form of pointers, but pointers are not just pointer variables.
2. Arrays
The array is defined as follows:
Array types is characterized by their element type and by the number of the elements in the array. An array type was said to being derived from it element type, and if its element type was T, the array type is sometimes call Ed "Array of T". The construction of an array type from a element type is called "Array type derivation".
An array type is also a derived type that describes a contiguous, non-empty set of objects, characterized by the element type and the number of elements.
As can be seen by pointers and array definitions, pointers and arrays are completely different types. But is the array name a pointer?
According to the book conquering the C-pointer, the array name is not a pointer, but in the expression , the array name can be interpreted as "a pointer to its initial element".
In a post chapter II is the array name a pointer constant? , the author is more thorough in analysis:
“
The array name is a pointer constant, which is derived from the equivalence of the result of the array name to the pointer in the expression evaluation. For example, the following code:
1 int a[], *p = A, *q; 2 1 ; 3 1;
In effect, a + 1 and P + 1 are the same, it is easy to give a is the illusion of P, but, this is just an illusion.
In the book "C and Pointers", the author uses a well-known example to illustrate the difference between the array name and the pointer. Defined in one file:int a[10]; then declare in another file:extern int *a; I do not repeat the principle here, the author of the book is trying to explain the difference between the array name and the pointer from the underlying operation, but I think this example has some shortcomings, A in the expression will be converted to a non-object of the symbolic address, and pointer A is an object, with a non-object to compare with an object, there is a "steal" suspicion, this example simply shows the array name of the non-object nature, can only prove that the object and non-object entities in the underlying operation of the difference, in fact, As mentioned in the previous chapter, pointers also have non-object patterns. The author argues that it is not necessary to spend so much of your breath from the underlying point of view, just literal semantics can overturn the idea that the array name is a pointer.
First of all, the array type and pointer type are two different derived types, and the array name and pointer are two different types of entities, and it is absurd to say that the entity of the array type is "yes" and another type of entity.
Second, the effect of a + 1 is equivalent to P + 1, because A is an array-to-pointer implicit conversion , which is a process of conversion, converted to rather than is a. If there are two identical things, how can there be a process of conversion? When a is placed in a + 1 expression, A has been converted from an array name to a pointer, a is a pointer instead of the array name to participate in the operation;
Thirdly,A + 1 and P + 1 are equivalent relationships, not equivalence relations. equivalence is the different manifestation of the same thing, and equivalence is the same effect of different things. The equivalent relationship is misinterpreted by the fact that the array name is a pointer.
Therefore, the array name is not a pointer and is never, but under certain conditions, the array name can be converted to a pointer.
”
According to chapter 8th 8.1 of the book "C and Pointers", the author mentions that "only if the array name is used in an expression does the compiler produce a pointer constant for it". Note that this value is a pointer constant, not a pointer variable. We cannot modify the value of a constant. In both cases, the array name is not represented by a pointer constant in the expression--that is, when the array name is used as the operand of the sizeof operator or the monocular operator &. sizeof returns the length of the entire array, not the length of the pointer to the array. Taking an address of an array name results in a pointer to an array instead of a pointer to a pointer constant value.
In summary, the array is not a pointer, and the array name is treated as a pointer constant only in the expression.
is the subscript operator [] and array related?
For the subscript operator, I'm sure we're all familiar with it, so we can easily access the elements in the array quickly. But is it related to the array? Let's look at an example:
1#include <iostream>2 using namespacestd;3 4 intMain ()5 {6 intp[Ten];7 for(inti =0; I <Ten; i++)8P[i] = i +1;9 Tencout <<"* (p + i) \ t"<<"P[i]"<<Endl; One for(inti =0; I <Ten; i++) Acout << * (P + i) <<"\t\t"<< P[i] <<Endl; - - return 0; the}
The output of the program is as follows:
So, the effect of * (P + i) is the same as p[i]. According to the conquest of the C-pointer,P[i] is simply a simple notation for * (P + i). In fact, at least for the compiler, [] Such an operator can simply not exist. The [] operator is a syntactic sugar that is introduced to facilitate reading and writing by people.
Note that [] in the absence of [] and array relationships means that the subscript operator appears in the expression instead of [] in the declaration.
Two-level pointers and pointer arrays
A second-level pointer is a short name for pointers to pointers, as in the following common examples:
int **p;
The pointer array is an array of element type pointers, such as:
int *p[];
Two-level pointer and pointer array differences and linkages
We know that pointers and arrays are not the same, and of course two-level pointers and pointer arrays are not the same. So what's their connection?
Below, consider an example:
For the main function, two common ways to do this are as follows:
int Main (intchar *argv[]);
Or
int Main (intchar **argv);
According to the Linux C programming one-stop learning statement, the function prototype []
represents pointers rather than arrays , equivalent to char **argv
. Why do you write it char *argv[]
and not write it char **argv
? This provides useful information to the person reading the code, argv
not to a single pointer, but to the first element of an array of pointers. Each element in the array is a char *
pointer to a command-line argument string.
In fact, even in an expression, they are equivalent.
How do two-level pointers and pointer arrays represent two-dimensional arrays?
In an expression, a level two pointer and an array of pointers are equivalent. So we can just use a level two pointer to illustrate the following.
For a level two pointer, the first level pointer points to the first element of an array of pointers, so that each element of the pointer array is obtained by using the subscript operator [], whereas each element of the pointer array stores a pointer that can then point to another array. In this way, we can use a level two pointer to implement a two-dimensional array, as in the following example:
Let's look at a simple example:
1#include <stdio.h>2#include <stdlib.h>3#include <string.h>4 5 intMainintargcChar*argv[])6 {7 inti;8 for(i =0; i < argc; i++)9 {Tenprintf"argv[%d]=%s\t", I, Argv[i]); One intLen =strlen (Argv[i]), J; A for(j =0; J < Len; J + +) -printf"%s[%d]=%c", Argv[i], J, Argv[i][j]); -printf"\ n"); the } - return 0; -}
Compile the execution under Linux:
Second-level pointer magic: Delete one-way linked list
Main references:
Both star programming
Linus: The use of two-level pointer to delete the one-way list (with a detailed explanation, very worthy of reference!) )
When deleting a one-way list (retaining head pointer Head), we might take a more typical approach:
1typedefstructnode2 {3 structNode *Next;4 ....5 } node;6 7typedefBOOL(* remove_fn) (nodeConst*v);8 9 //Remove all nodes from the supplied list for which theTen //supplied Remove function returns TRUE. One //Returns The new head of the list. ANode * REMOVE_IF (node *Head, REMOVE_FN RM) - { - for(node * prev = NULL, * Curr = head; Curr! =)NULL;) the { -Node *ConstNext = curr->Next; - if(RM (Curr)) - { + if(prev) -Prev->next =Next; + Else AHead =Next; at Free(Curr); - } - Else -Prev =Curr; -Curr =Next; - } in returnhead; -}
But Linus aunt will say this like the person who wrote: "This man doesn ' t understand pointers". That for Linus, how to do is the best? That's the use of level two pointers, specifically as follows:
1 voidREMOVE_IF (Node *Head, REMOVE_FN RM)2 {3 for(node** Curr = head; *Curr;)4 {5Node * Entry = *Curr;6 if(RM (entry))7 {8*curr = entry->Next;9 Free(entry);Ten } One Else ACurr = &entry->Next; - } -}
Sure enough, the rewritten program is a lot more concise, and there is no need to maintain a prev table item pointer and consider the head pointer problem.
In the post Linus: Using a Level two pointer to delete a one-way list, the author also attached a more detailed explanation to the array using level two pointers:
“
For--
- Delete node is the case of the table header, input parameters in the head of the two-level pointer, in the FOR loop to initialize it Curr, and then entry is *head (*curr), we immediately delete it, then the 8th line is equivalent to *head = (*head)- >next, is the implementation of deleting the header.
- The deletion of the node is not a table header , for the above code, we can see--
1)(line 12th) If you do not delete the current node--curr the address of the current node next pointer is saved .
2) (line 5th) entry saved *curr - This means the next loop: entry is the memory that the Prev->next pointer points to.
3) (line 8th) Delete node: *curr = entry->next; -So: Prev->next points to entry, next;
”
Resources
The conquest of the C-pointer
"C and Pointers"
The first chapter analysis of the concept of arrays and pointers
The second chapter is the array name a pointer constant?
Linux C Programming One-stop learning
Both star programming
Linus: Delete one-way linked list with level two pointers
Pointer and array parsing