In-depth understanding of C / C ++ arrays and pointers

Reprinted: http: //blog.csdn.net/walkinginthewind/article/details/7044380

 

C language arrays and pointers is a very special relationship, first of all in nature is certainly different, this article discussed from all angles and an array of pointers.

 

First, the relationship between arrays and pointers

Arrays and pointers are two different types of arrays having a determined number of elements, but only a pointer scalar value. Arrays can be converted to a pointer, in some cases, when the array name used in an expression, the compiler will convert an array name pointer constant, is the address of the first element in the array, the array elements is the address type type, such as:

int a[5]={0,1,2,3,4}; 

If there is a name in the array expression, such as int * p = a; then it is converted into the address of the first element, equivalent to int * p = & a [0];

another one:

int aa[2][5]={0,1,2,3,4,   

                      5,6,7,8,9};

If the array name aa appear in an expression, such as int (* p) [5] = aa; then it is converted into the address of the first element, is equivalent to int (* p) [5] = & aa [0] ; 

However, int (* p) [5] = aa [0]; this is not right, the rules we push the very clear, aa [0] is of type int [5], the number of elements is an integer of 5 array, even if the transformation, then transformed into an array (int [5]) of the address of the first element & aa [0] [0], type int *. Therefore, either int (* p) [5] = aa; either int (* p) [5] = & aa [0];

In both cases only, the name of the array is not constant for the pointer - that is, when an operand array name as sizeof operator or the unary & operator, sizeof returns the length of the entire array, using the type information it instead of the address information, the length of the pointer is not pointing to the array. A fetch address generated by the array name is a pointer to an array of pointers, rather than the pointer to point to a pointer to a constant value.

As for the array a, & a represents the point array a pointer type int (*) [5], so int * p = & a; is wrong, since the right side is a pointer int an integer array (*) [5 ], and p is an integer pointer int *;

sizeof array of issues will be discussed below carefully.

Second, the reference pointer array subscript

int a[5]={0,1,2,3,4}; 

As a [3], with the subscript to access the array a third element, then the next target is essentially what is? This is essentially an expression: * (a + 3), of course, must contain a valid expression array name or pointer variables.

In fact, a [3] and 3 [a] are equivalent because they are translated into the same expression (at most, only in a different order), they are accessible in a array of 3 elements.

Of course, the pointer can form the subscripts, such as: int * p = a; then p [3] is * (p + 3), equivalent to 3 [p] (not evil ... 3P, 3P), the same access a 3 element in the array.

According to this rule, we can write more strange expressions, such as:

int aa[2][5]={0,1,2,3,4,

                      5,6,7,8,9};

1 [aa] [2], this looks very awkward, the first 1 [aa], that is, * (1 + aa), then 1 [aa] [2] is * (* (1 + aa) +2), also It is aa [1] [2].

1 [2] [AA], this is not on, because the first half of 1 [2] is undesirable.

Of course, the use of such expressions in practice does not make sense, unless just do not want people to easily understand your code.

Third, the definitions and declarations of arrays and pointers

Definition and declare arrays and pointers must be consistent, not a place defined by an array, and then another place declared as a pointer.

First, we explain the application subscript subscript array name references and pointers, they are not exactly the same, from the way in terms of access.

int a[5]={0,1,2,3,4};

int *p=a;

For a [3], and p [3] are parsed into * (a + 3) and * (p + 3), but the substance is not the same.

First, for a [3], i.e. * (a + 3):

(1) the first address of the array and the array name A represents a 3 added to obtain the address of the data to be accessed, where noted, the array name is directly translated into a first address of the array;

(2) access the address data extracted.

For p [3], i.e. * (p + 3):

(1) from the address unit where p represents the contents of the array is the first address, name of the pointer p represents the memory address pointer variable, the first address unit is stored in the variable array;

(2) the first address and the extracted array 3 is added to obtain the address of the data to be accessed;

(3) access the address data extracted.

Here's an example to illustrate the problem if inconsistent definitions and declarations brought:

There is provided test1.cpp defined as follows:

char s[]="abcdefg";

test2.cpp in the following statement:

extern char *s;

Obviously compilation is not a problem.

So references s [i] result in test2.cpp happen then? The s [3], a 'd' it? It seems

Here we analyze test2.cpp in s [3]:

s address course, be determined by the definitions in the test1.cpp, since only the memory space allocated defined above;

We calculate according to the procedure given above referenced index pointer

(1) taken from the contents (4 bytes) of the address locations represented by s, where s is actually an array of first 4 elements, this value is "abcd", i.e. hexadecimal 64636261h, this step should be We can see the problem;

(2) The first address is then extracted by adding and 3, to obtain the address of the data to be accessed 64636261h + 3, the address is not assigned undefined;

(3) to take the contents of the address 64636261h + 3, this means is undefined address, access error occurs.

The following analysis is given the code (which may simply observe the annotated section):

#include<iostream>         
using namespace std;
extern void test();
char s[]="abcdefg";
int main()
{
002E13A0  push        ebp  
002E13A1  mov         ebp,esp  
002E13A3  sub         esp,0D8h  
002E13A9  push        ebx  
002E13AA  push        esi  
002E13AB  push        edi  
002E13AC  lea         edi,[ebp+FFFFFF28h]  
002E13B2  mov         ecx,36h  
002E13B7  mov         eax,0CCCCCCCCh  
002E13BC  rep stos    dword ptr es:[edi]  
    char ch;
    int= I . 3 ; 
002E13BE MOV DWORD PTR [EBP -14h], . 3   
    CH = S [I]; 
002E13C5 MOV EAX, DWORD PTR [EBP - 14H]   
002E13C8 MOV Cl, byte PTR [EAX + 011F7000h]   / * S is directly translated into first address array and i (eax) adding address of the operand, and then taking as the content type byte ptr, pass Cl * / 
002E13CE MOV          byte PTR [EBP . 5 ], Cl           / * Cl content passed ch (ebp -5) * / 
    Test (); 
002E13D1 Call 002E1073   
    return  0 ; 
002E13D6 XOR EAX, EAX   
} 
002E13D8 POP EDI   
002E13D9 POP ESI  
002E13DA  pop         ebx  
002E13DB  add         esp,0D8h  
002E13E1  cmp         ebp,esp  
002E13E3  call        002E113B  
002E13E8  mov         esp,ebp  
002E13EA  pop         ebp  
002E13EB  ret  

test2.cpp // run error

extern char *s;
void test()
{
011F1470  push        ebp  
011F1471  mov         ebp,esp  
011F1473  sub         esp,0D8h  
011F1479  push        ebx  
011F147A  push        esi  
011F147B  push        edi  
011F147C  lea         edi,[ebp+FFFFFF28h]  
011F1482  mov         ecx,36h  
011F1487  mov         eax,0CCCCCCCCh  
011F148C  rep stos    dword ptr es:[edi]  
    char ch;
    int i=3;
011F148E  mov         dword ptr [ebp-14h],3  
    ch=s[i];
MOV EAX 011F1495, DWORD PTR DS: [011F7000h]   / * no effect DS, because the windows of all segment numbers are 0, take the contents 011F7000h unit, where the array is the first four bytes (words pointers section) composed of an integer, i.e. 64636261h, i.e. where the calculating unit referred to in s become 64636261h * / 
011F149A the Add EAX, DWORD PTR [EBP -14h]        / * then the address is added to i, i.e. 64636261h +3, the address is unassigned defined, of course, access error * /  
011F149D MOV Cl, byte PTR [EAX]              / * access error * / 
011F149F MOV          byte PTR [EBP . 5 ], Cl  
     return ; 
} 
011F14A2 POP EDI   
011F14A3 ESI POP   
011F14A4 POP EBX   
011F14A5 mov ESP, ebp  
011F14A7 pop EBP   
011F14A8 ret  

If test2.cpp in this statement:

extern char s[];

This right, because the consensus statement and define, access, no problem.

So do not simply that the name of the array and pointers are the same, otherwise they will suffer a great deal, an array of definitions and declarations sure to maintain consistency.

Fourth, arrays and pointers sizeof problem

sizeof array is the number of array elements * element size, and a pointer sizeof all the same, are address type, the machine 32 is four bytes.

Some examples are given below:

test program:

#include<iostream>                        
using namespace std;
int main()
{
    int a[6][8]={0};
    int (*p)[8];
    p=&a[0];    
    int (*pp)[6][8]; 
    pp=&a;
 
    cout<<sizeof(a)<<endl;        // 192
    cout<<sizeof(*a)<<endl;       // 32
    cout<<sizeof(&a)<<endl;       // 4
    cout<<sizeof(a[0])<<endl;     // 32
    cout<<sizeof(*a[0])<<endl;    // 4
    cout<<sizeof(&a[0])<<endl;    // 4
    cout<<sizeof(a[0][0])<<endl;  // 4
    cout<<sizeof(&a[0][0])<<endl; // 4
    cout<<sizeof(p)<<endl;        // 4
    cout<<sizeof(*p)<<endl;       // 32
    cout<<sizeof(&p)<<endl;       // 4
    cout<<sizeof(pp)<<endl;       // 4
    cout<<sizeof(*pp)<<endl;      // 192
    cout<<sizeof(&pp)<<endl;      // 4 
 
    system("pause");
    return 0;
}

VS2010 running under 32-bit result windows7 (VC6.0-standard):

192

32

4

32

4

4

4

4

4

32

4

4

192

4

The following program do one by one simple explanation:

(1) sizeof (a); a is defined as A int [6] [8], type int [6] [8], i.e. the number of elements is a two-dimensional array of 6x8 int type, which is the size of 6 * 8 * sizeof (int), this is 192;

(2) sizeof (* a); * a this expression array name is converted to a pointer, i.e., the first element of the array a [0] to address '*' to obtain the address refers to an object, i.e. a [0], * a generally equivalent to * (& a [0]), a [0] of type int [8], i.e., the size of a one-dimensional array of type int. 8, its size is 8 * sizeof (int), in this case 32;

(3) sizeof (& a); '&' a second address, the type is int (*) [6] [8], address type, where size is 4;

(4) sizeof (a [0]); a [0] of type int [8], i.e., the size of a one-dimensional array of type int. 8, its size is 8 * sizeof (int), in this case 32;

(5) sizeof (* a [0]); * a [0] In this expression the name of the array a [0] is converted to a pointer, i.e., the first element of the array a [0] [0] address, ' * 'refers to this address element obtained, i.e. a [0] [0], in general * a [0] is equivalent to * (& a [0] [0]), a [0] [0] it is of type int, which is the size sizeof (int), here 4;

(6) sizeof (& a [0]); '&' takes a [0] address, type int (*) [8], address type, where size is 4;

(7) sizeof (a [0] [0]); a [0] [0] is of type int, which is the size sizeof (int), here 4;

(8) sizeof (& a [0] [0]); '&' takes a [0] [0] address, type int *, address type, where size is 4;

(9) sizeof (p); p is the type int (*) [8], a number of elements pointing to int array 8, address type, where size is 4;

(10) sizeof (* p); * p p elements made within the meaning of type int [8], a size of 8 * sizeof (int), in this case 32;

(11) sizeof (& p); '&' taking the address p, the type is int (**) [8], address type, where size is 4;

(12) sizeof (pp); pp type is int (*) [6] [8], pointing to a size of two-dimensional array of 6x8 int type, address type, where the size of 4,

(13) sizeof (* pp); pp achieve the object referred pp *, type int [6] [8], i.e. the number of elements is a two-dimensional array of 6x8 int type, which is the size of 6x8 * sizeof (int), this is 192;

(14) sizeof (& pp); '&' taken pp address, the type is int (**) [6] [8], address type, where size is 4;

Fifth, the array as a function parameter

When passed as an argument array, the array pointer is degraded, a first type address type element. "Array name is rewritten as a pointer parameter", this rule is not recursive definition. An array of arrays can be rewritten as "an array of pointers," not "pointer pointers."

Here are a few examples:

fun1(char s[10])

{

The actual type of function is internally // s char *;

}

 

fun2(char s[][10])

{

// s inside the actual type of function is char (*) [10], i.e. the pointer char [10] of the array;

}

 

fun3(char *s[15])

{

// s function within the actual type is a pointer char **, char pointer;

}

 

fun4(char(*s)[20])

{

// s constant inside the actual type of function, it is still [20] array of pointers to char (*) [20], i.e. char;

}

Above may be summarized as a simple array as a parameter is rewritten to point to the first element of the array (where the elements can be an array) pointer. Array as a parameter to provide all dimensions except the length of the left-most dimension. We also noted that char s [] [10] and the char ** s as a function of different parameters, as a function of the type of internal pointers are not the same, especially when performing subtraction, and the sizeof pointer.

 

to sum up:

Summed up so much, there should be a more in-depth understanding of arrays and pointers. In the final cause of these problems comes from the pointer issue, which is the essence of the c language, do not have not mastered these fundamental c language, but do not dare to master these is equivalent to master the language c :) 

 

 

 

net / walkinginthewind / article / details / 7044380 </a> <br> </ span> </ strong> </ p> <p> C language arrays and pointers is a very special relationship, first of all in nature is certainly different from all angles discussed herein, and an array of pointers. </ P> <strong> <span style = "font-size: 16px;"> a, the relationship between the pointer array </ span> </ strong> <br> pointers and arrays are two different types, having an array of determining the number of elements, but only a pointer scalar value. Arrays can be converted to a pointer, in some cases, when the array name used in an expression, the compiler will convert an array name pointer constant, is the address of the first element in the array, the array elements is the address type type, such as: <br> int a [5] = {0,1,2,3,4}; & nbsp; <br> If there is a name of the array in the expression, such as int * p = a; then it converting the address of the first element, equivalent to int * p = & amp; a [0]; <br> encore: <br> int aa [2] [5] = {0,1,2,3, 4, & nbsp; & nbsp; <br> & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; 5,6,7,8,9}; <br> array name aa If there in the expression, such as int (* p) [5] = aa; then it is converted into the address of the first element, is equivalent to int (* p) [5] = & amp; aa [0]; & nbsp; However <br> int (* p) [5] = aa [0]; This is not right, according to the rules we push a very clear, aa [0] is of type int [5], is the number one element integer array 5, even if the conversion is then converted into an array of (int [ address of the first element 5]) is & amp; aa [0] [0], type int *. Therefore, either int (* p) [5] = aa; either int (* p) [5] = & amp; aa [0]; <br> only in both cases, the array pointer constants were not represents - that is, when the array name as sizeof operator or unary operator & amp; operand of sizeof returns the length of the entire array, using its type information, not the address information is not pointing to the length of the pointer array . A fetch address generated by the array name is a pointer to an array of pointers, rather than the pointer to point to a pointer to a constant value. <br> The array a, & amp; a represents the pointer to array a, type int (*) [5], so int * p = & amp; a; is wrong, because the right is a shaped array pointer int (*) [5], and p is an integer pointer int *; sizeof array <br> problem carefully discussed below. <br> <strong> <span style = "font-size: 16px;"> Second, the array index pointer references </ span> </ strong> <br> int a [5] = {0,1, 2,3,4}; & nbsp; <br> as a [3], with the subscript to access the array a third element, then the next target is essentially what is? This is essentially an expression: * (a + 3), of course, must contain a valid expression array name or pointer variables. In fact, a <br> [3] and 3 [a] are equivalent because they are translated into the same expression (at most, only in a different order), are accessible in a array of 3 elements. <br> pointer can of course form the subscripts, such as: int * p = a; & nbsp; Then p [3] is * (p + 3), equivalent to 3 [p] (not evil ... 3P, 3P), the same access elements of the array a 3. <br> According to this rule, we can write more strange expressions, such as: <br> int aa [2] [5] = {0,1,2,3,4, <br> & nbsp; & nbsp ; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; & nbsp; 5,6,7,8,9}; <br> 1 [aa] [2], this looks very awkward, first 1 [ aa], is * (1 + aa), then 1 [aa] [2] is * (* (1 + aa) +2), i.e. aa [1] [2]. <br> 1 [2] [aa], this is not right, because the first half of 1 [2] does not meet the requirements. <br> of course use such expressions in practice does not make sense, unless just do not want people to easily understand your code. <br> <strong> <span style = "font-size: 16px;"> III definitions and declarations of the array pointer </ span> </ strong> definitions and declarations <br> arrays and pointers must be consistent, not a place defined by an array, and then another place declared as a pointer. <br> First, we explain the application subscript subscript array name references and pointers, they are not exactly the same, from the way in terms of access. <br> int a [5] = {0,1,2,3,4}; <br> int * p = a; <br> for a [3], and p [3] are parsed into * (a + 3) and * (p + 3), but the essence is not the same. <br> first for a [3], that is, * (a + 3): <br> (1) the first address of the array array name a representative and 3 is added to obtain the address to access the data, pay attention here, array a name directly compiled into the first address of the array; <br> (2) access the address data extracted. For <br> p [. 3], i.e. * (p + 3): <br> (1) taken out from the address unit represented by p, the array is the first address, name of the pointer p represents a pointer variable is stored first address of the address unit, is stored in the variable array; <br> (2) the first address and the extracted array 3 is added to obtain the address of the data to be accessed; <br> (3) to access this address , extract data. <br> an example is given below to illustrate the problem, if inconsistent definitions and declarations bring: <br> provided in test1.cpp defined as follows: <br> char s [] = "abcdefg"; <br> test2.cpp in the following statement: <br> extern char * s; <br> compiler is apparently not a problem. <br> then cited s [i] result in test2.cpp happen then? The s [3], a 'd' it? Here it seems we <br> test2.cpp in s [3] analyzed: <br> s address determines the course test1.cpp are defined by as defined when allocating memory space; < br> we calculate <br> (1) from the address extraction unit represented by s contents (4 bytes) according to the procedure given above referenced by a pointer index, where s is actually the first 4 array elements this value is "abcd", that is, 16 hex 64636261h, this step should be able to see the problem; <br> (2) and the first address out of 3 and added to obtain the address of the data to be accessed 64636261h + 3, the address is not assigned undefined; <br> (3) to take the contents of the address 64636261h + 3, this means is undefined address, access error occurs. <P> The following analysis is given the code (which may simply observe the annotated section): </ p> <p> </ p> <pre> <code class = "language-cpp hljs"> < data-line-number = "29"> </ div> </ div> <div class = "hljs-ln-code"> <div class = "hljs-ln-line"> <span class = "hljs-number "> 011F </ span> 14A8 ret </ div> </ div> </ li> </ ol> </ code> <div class =" hljs-button {2} "data-title =" copy "onclick = "hljs.copyCode (event)"> </ div> </ pre> if test2.cpp in this statement: <br> extern char s []; <br> so correctly, because the consensus statement and definition, access to No problem. <br> so do not simply that the name of the array and pointers are the same, otherwise they will suffer a great deal, an array of definitions and declarations sure to maintain consistency. <br> <strong> <span style = "font-size: 16px;"> four, sizeof problems arrays and pointers </ span> </ strong> sizeof <br> array is the number of elements in the array element size * , sizeof pointer and all the same, are address type, the machine 32 is four bytes. Some examples are given below <br>: <br> test procedure: <br> <pre> <code class = "language-cpp hljs"> <ol class = "hljs-ln" a [0]), a [0] of type int [8], i.e., the size of a one-dimensional array of type int. 8, its size is 8 * sizeof (int), where is 32; <br> (3) sizeof (& amp; a); '& amp;' taking the address of a, type int (*) [6] [8], address type, where size is 4; <br> (4) sizeof (a [0]); a [0] of type int [8], i.e., the size of a one-dimensional array of type int. 8, its size is 8 * sizeof (int), where is 32; <br> (5) sizeof (* a [0] ); * a [0] in this expression the name of the array a [0] is converted to a pointer, i.e., the first element of the array a [0] [0] address, '*' to obtain the address element refers to, i.e. a [0] [0], in general * a [0] is equivalent to * (& amp; a [0] [0]), a [0] [0] is of type int, its size It is sizeof (int), here 4; <br> (6) sizeof (& amp; a [0]); '& amp;' takes a [0] address, type int (*) [8], address type , where size is 4; <br> (7) sizeof (a [0] [0]); a [0] [0] is of type int, which is the size sizeof (int), here 4; <br > (8) sizeof (& amp; a [0] [0]); '& amp;' takes a [0] [0] address, type int *, address type, where size is 4; <br> (9 ) the sizeof (p); p is the type int (*) [8], a number of elements pointing to int array 8, address type, where size is 4; <br> (10) sizeof (* p); * refers to obtain p p elements, type int [8], a size of 8 * sizeof (int), where is 32; <br> (11) sizeof (& amp; p); '& amp;' Let p address, type int (**) [8], address type, where size is 4; <br> (12) sizeof (pp); pp type is int (*) [6] [8], point two-dimensional size of a 6x8 array of type int, address type, where the size of 4, <br> (13) sizeof (* pp); * pp pp achieve the object referred to, is a type of int [6] [ 8], i.e. the number of elements is a two-dimensional array of 6x8 int type, which is the size of 8 * 6 * the sizeof (int), this is 192; <br> (14) sizeof (& amp; pp); '& amp ; 'pp taken address, type int (**) [6] [8], address type, where size is 4; <br> <strong> <span style = "font-size: 16px;"> V. an array as a function parameter </ span> </ strong> <br> when the array is passed as function arguments, degenerate pointer array, a first type address type element. "Array name is rewritten as a pointer parameter", this rule is not recursive definition. An array of arrays can be rewritten as "an array of pointers," not "pointer pointers." <br> few examples are given below: <br> fun1 (char s [10]) <br> {<br> // s actual type within a function is char *; <br>} <br> <br > fun2 (char s [] [10]) <br> {<br> // s inside the actual type of function is char (*) [10], i.e. the pointer char [10] of the array; <br>} < br> <br> fun3 (char * s [15]) <br> {<br> // s inside the actual type of function is char **, character pointer pointer; <br>} <br> <br > fun4 (char (* s) [20]) <br> {<br> // s constant inside the actual type of function, is still [20] array of pointers to char (*) [20], i.e. char; < br>} <br> above can be summarized as a simple array as a parameter is rewritten to point to the first element of the array (where the elements can be an array) pointer. Array as a parameter to provide all dimensions except the length of the left-most dimension. We also noted that char s [] [10] and the char ** s as a function of different parameters, as a function of the type of internal pointers are not the same, especially when performing subtraction, and the sizeof pointer. <br> <br> <strong> <span style = "font-size: 16px;"> summary: </ span> </ strong> <br> summed up so much, there should be a more in-depth on arrays and pointers I understand. In the final cause of these problems comes from the pointer issue, which is the essence of the c language, do not have not mastered these fundamental c language, but do not dare to master these is equivalent to master the c language:) & nbsp; < br> <br> </ div> </ div> span style = "font-size: 16px;"> summary: </ span> </ strong> <br> summed up so much, there should be a more in-depth understanding of the arrays and pointers. In the final cause of these problems comes from the pointer issue, which is the essence of the c language, do not have not mastered these fundamental c language, but do not dare to master these is equivalent to master the c language:) & nbsp; < br> <br> </ div> </ div> span style = "font-size: 16px;"> summary: </ span> </ strong> <br> summed up so much, there should be a more in-depth understanding of the arrays and pointers. In the final cause of these problems comes from the pointer issue, which is the essence of the c language, do not have not mastered these fundamental c language, but do not dare to master these is equivalent to master the c language:) & nbsp; < br> <br> </ div> </ div>

Guess you like

Origin www.cnblogs.com/fuao2000/p/11006211.html