当前位置:网站首页>C language pointer

C language pointer

2022-06-11 03:07:00 shlyyy


Preface

I am learning C Language pointer related content , Include pointer array 、 Array pointer 、 A function pointer , Always confused , And learn to forget , Forget to learn , Go back and forth . My understanding of this part is summarized as follows .

If you can understand why the following code is written , There is no need to waste time reading this article .

int main(int argc, char* argv[])
{
    
    int ary1[4] = {
     1,2,3,4 };
    int *p1 = ary1;
    int(*p2)[4] = &ary1;
  
    int nAry[2][4] = {
    
        {
    10,20,30,40},
        {
    60,70,80,90}
    };
    int(*p3)[4] = nAry;
    int (*p4)[2][4] = &nAry;

    return 0;
}
(*(void(*)())0)();
void (*signal(int, void(*)(int n)))(int n);
int main(int argc, char* argv[])
{
    
    int(*pfun[2])(int a, int b);
    int(**pPfun)(int a, int b) = pfun;
    return 0;
}
int main(int argc, char* argv[])
{
    
    int(*pfun[2])(int a, int b);
    int(*(*pPfun)[2])(int a, int b) = &pfun;
    return 0;
}

One 、 Array recognition

1.1 One dimensional array subscript operation ([])

The result of the subscript operation gets a reference to its element .

Subscript operation requires an operand of integer type , The other operand is the address .

int main(int argc, char* argv[])
{
    

    int ary[5] = {
     1, 2 };

    // &2[ary] = &ary[2];
    printf("%p\r\n", &ary[2]); // 0019FED0
    printf("%p\r\n", &2[ary]); // 0019FED0

    system("pause");
    return 0;
}

*(arr + n) = arr[n]

int main(int argc, char* argv[])
{
    
    int ary[5] = {
     5,4,3,2,1 };
    int* ptr = (int*)(&ary + 1);
    printf("%d\n", *(ptr - 1)); // 1
    return 0;
}

&ary in ary Represents the entire array , therefore ptr Pointing to the array ary After the last element of the , That is, skip the array ary.

1.2 One dimensional array addressing mode

Addressing mode of one-dimensional array :
type ary[M] = …; ary[n] address is:
(int)ary + sizeof(type) * n

int main(int argc, char* argv[])
{
    
    int ary[2] = {
     0 };

    // 0x400000 Situated MZ identification 
    printf("%p\r\n", (void*)ary[(0x400000 - (int)ary) / sizeof(int)]); // 00905A4D

    printf("%s\r\n", (char*)&ary[(0x400000 - (int)ary) / sizeof(int)]); // MZ?

    system("pause");
    return 0;
}

1.3 Two dimensional array

Two dimensional arrays are special one-dimensional arrays , Array elements are arrays of one-dimensional arrays

int ary[2][3] = {
    
    {
    1,2,3},   // ary[0]
    {
    4,5,6}    // ary[1]
};

// ary There are two elements , Each element is int[3] type 
int[3] ary[2] = {
    
    {
    1,2,3},
    {
    4,5,6}
};

//  Two subscript operations , The first subscript operation yields ary[1], For a one-dimensional array 3 Elements 
//  The second subscript operation starts from ary[1] Take the th... From the one-dimensional array of 2 Elements get data 
ary[1][2];

Two dimensional array addressing mode

type ary[N][M] = ...;
int x,y = ...;

ary[x][y] address is:
(int)ary + sizeof(type[M])*x + sizeof(type)*y
==> (int)ary + sizeof(type)*M*x + sizeof(type)*y
==> (int)ary + sizeof(type)*(M*x + y)
ary[0][M*x + y] <==> ary[x][y]

*(arr + n) = arr[n]

int main(int argc, char* argv[])
{
    
    int ary[2][5] = {
     10,9,8,7,6,5,4,3,2,1 };
    int* ptr1 = (int*)(&ary + 1);
    int* ptr2 = (int*)(*(ary + 1));
    printf("%d,%d\n", *(ptr1 - 1), *(ptr2 - 1)); // 1 6

    return 0;
}

&ary in ary Represents the entire array , therefore ptr1 Pointing to the array ary After the last element of the , That is, skip the array ary.

Array name ary Represents the address of the first element , That is to say ary[0] The address of ,*(ary + 1) = ary[1], therefore ptr2 Point to ary[1].

1.4 summary

  1. except sizeof(arr) and &arr Array name in arr, Array names that appear elsewhere arr, Are the address of the first element of the array .
  2. *(arr + n) = arr[n]

Two 、 The pointer

A pointer is a variable , The address where the memory unit is stored . Indirect operation of memory unit through pointer , The type of pointer determines whether the pointer moves forward or backward ( Pointer addition and subtraction 1) How big is the , And the pointer type determines how the pointer is interpreted ( Dereference the pointer *).

In conclusion , The pointer = Address + Mode of interpretation

2.1 int* pa, p;

int main(int argc, char* argv[])
{
    
    int ary[4] = {
     1,2,3,4 };
    int* pa, p; // pa For the pointer ,p Is an integer .
    
    pa = ary;
    p = ary; // “=”:“int” And “int *” Different levels of indirection 

    return 0;
}

2.2 Pointer arithmetic

1. Pointer plus integer gets pointer constant of the same type

2. Subscript the pointer , Get variable references to pointer types

3. Pointers of the same type can be subtracted , The result is an integer constant

type *p = ...;
int n = ...;

// 1. Pointer plus integer gets pointer constant of the same type 
p + n = (int)p + n*sizeof(type);

// 2. Subscript the pointer , Get variable references to pointer types 
p[n] = *(type*)((int)p + n*sizeof(type));
type *p1 = ...;
type *p2 = ...;

// 3. Pointers of the same type can be subtracted , The result is an integer constant 
p1 - p2 = ((int)p1 - (int)p2) / sizeof(type);

2.3 *p++ And *++p

* With the priority of ++ Same priority for , The priority is 2, And they are all combined from right to left .

*p++: First, execute p++, But post ++ After the whole statement is executed p Again ++. And then execute *p Value . Last p+=1. Equate to *p;p+=1;

void mystrcpy(char* szDst, char* szSrc)
{
    
    while(*szDst++ = *szSrc++);
}

*++p: From right to left ,++p Execute first , After execution p Updated to p+1, And then take the value . Equate to :p+=1;*p;

2.4 The function of two-dimensional pointer

A two-dimensional pointer as a pointer , It can also be used as a formal parameter , Make indirect access to the two-dimensional pointer in the function , To modify the arguments ( One dimensional pointer & operation ), So as to achieve the purpose of modifying one-dimensional pointer .

int g_nTest = 0x123;
//  Pass out the pointer through the parameter , To pass in a second level pointer 

//  Pass on pn The address of is kept in ppn Parameter variables 
void SetPoint(int** ppn)
{
    
    //  Indirect access occurs   take pn The content of the address is modified 
    *ppn = &g_nTest;
}

int main(int argc, char* argv[])
{
    
    int n = 0x888;
    int* pn = &n;
    
    //  modify pn The direction of   Set up pn Save the address of the global variable 
    SetPoint(&pn);
    
    system("pause");
	return 0;
}

Another function of a two-dimensional pointer is to receive an array of pointers , See below .

3、 ... and 、 Pointer array

It's essentially an array , Is an array of pointers . such as main In the arguments of the function :

int main(int argc, char* argv[], char* envp[])
{
    
    //  Command line to argc Parameters as end flags 
	for (int i = 0; i < argc; i++)
	{
    
		puts(argv[i]);
	}

    //  Environment variables are represented by NULL As a closing sign 
	while (*envp != NULL)
	{
    
		puts(*envp);
		envp++;
	}
	system("pause");
	return 0;
}

A pointer array can be received with a two-dimensional pointer :

int main(int argc, char* argv[])
{
    
    char** p = argv;
    
	system("pause");
	return 0;
}

there argv As an array name , The array name is number 0 Elements (char * type ) Pointer constants for , That is to say char** type . So receive argv You need to define a two-dimensional pointer .


Advantages and disadvantages of pointer array :

advantage : It integrates the advantages of variable length storage and fixed length storage . It has the advantage of variable length storage and variable data size , It also has the advantage of random access of fixed length storage . When sorting, you only need to exchange the pointers in the array , There is no copy of the element . The problem of finding and sorting variable length storage has been solved .
shortcoming : When the data volume is large , Insertion and deletion are expensive .

Four 、 Array pointer

4.1 Array pointer to a one-dimensional array

4.1.1 Type of array name

To illustrate , We define the following two variables , integer Variable a, Array Variable ary1.

int a = 10;

int ary1[4] = {
     1,2,3,4 };

If, according to the definition of integer variables , If you want to define include 4 individual int Of type data Array ary1, The array ary1 The definition of should have been int[4] ary1;, But this kind of writing is not supported in grammar , It's written as int ary1[4];.

Although many books always say that arrays are non basic data types when talking about arrays , There is no problem with that , because int[4] Not a basic data type . But we always put the above array ary1 succeed in negotiation integer array ary1, This statement is easily misguided ary1 It's integral , But it is not , It should be said Array ary1 The member of is an integer , Or say A one-dimensional array containing integer data ary1. Although arrays are not basic types , But we put ary1 succeed in negotiation Integer array type variable ary1 Better understanding .

Java in int[4] ary1; And int ary1[4]; Both of these expressions support .C/C++ Support only int ary1[4]; This way of writing , After learning the compilation principle, we can infer that it is possible C/C++ Compiler in syntax or semantic analysis int[4] ary1; This way of writing conflicts with others .

All in all , What I want to say is to put the array ary1 It is understood as the same as ordinary variables , It's essentially a variable , The type of the variable is An array type , And is Integer array type , namely int[4]. So whether it's a one-dimensional array variable , Or two-dimensional array variables are the same .


actually , Array variables are array names , After introducing the pointer , The types of array variables need to be explained again .

For the sake of illustration , We still use one-dimensional arrays ary1.

int ary1[4] = {
     1,2,3,4 };

Here we throw out the conclusion directly :

The type of array name is array number 0 Pointer constants for elements

The array name of a one-dimensional array ary1 The type of is array number 0 Pointer constants for elements , Array number 0 Elements are 1 yes int type , So it should be int Pointer constant of type , That is int* const type .

int main(int argc, char* argv[])
{
    
    int ary1[4] = {
     1,2,3,4 };

    int* const p1 = ary1; // ary1 yes  int* const  type 

    return 0;
}

4.1.2 & Type of array name

Variable of a certain type & Operation to get pointers of the same type

The integer variable name takes the address to get the integer pointer , namely int Type variable & Operation result int A pointer to a type, that is int*.

int main(int argc, char* argv[])
{
    
    int a = 10;
    int* p = &a; // a by int type  &a by int* type 
    
    return 0;
}

Array names are also variables , Array variable name takes address to get array pointer , One dimensional array ary1 yes int[4] type , therefore &ary1 yes int[4]* type , Because the array pointer syntax does not support this kind of writing , So it should be written as int (*)[4], This is the array pointer .


4.1.3 The value of the array name

The above is the problem of array variable types . Let's discuss the value of array variables .

For variables of basic data type , Variable has memory space size , The binary value of a variable in its memory space is the value of the variable , adopt & Variable Get the address of the variable .

For array variables , Array variables determine the size of their memory space at compile time , But the value of an array variable is different from the value of a variable , Because the array contains many elements of the same type , In fact, the value of the array variable is the address of the array in the memory space , That is, the second of the array 0 The address of the elements in the memory space , Address of the first element of the array . and & An array variable It is still the address of the array in the memory space .

All in all , Array name 、& The value of the array name is the address of the first element of the array .

4.2 Array pointer to a two-dimensional array

int nAry[2][4] = {
    
	{
    10,20,30,40},
	{
    60,70,80,90}
};


//  It's equivalent to the following , However, the following writing methods are not supported grammatically 
int[4] nAry[2] = {
     //  How to write it 1
	{
    10,20,30,40},
	{
    60,70,80,90}
};
int[2][4] nAry = {
     //  How to write it 2
	{
    10,20,30,40},
	{
    60,70,80,90}
};

From writing 2 Look at , Two dimensional array nAry The type is int[2][4].

From writing 1 Look at , Two dimensional array nAry There are two elements , Each element is a int[4] That is to say int An array of types .


If you want to receive an array name :

The array name is number 0 Pointer constants for elements . Array name nAry Of the 0 Elements nAry[0] by int[4] type , therefore nAry yes int[4]* type . So you can define variables like this int[4] *p = nAry;, Also, the syntax does not support , The correct way to write it should be int (*p)[4] = nAry;.


If you want to receive & Array name :

Variable of a certain type & Operation to get pointers of the same type . An array is int[2][4] type , therefore &nAry yes int[2][4]* type , This kind of writing is not supported in grammar , Should be written as int (*p)[2][4] = &nAry.

4.3 This section summarizes

int main(int argc, char* argv[])
{
    

    int ary1[4] = {
     1,2,3,4 };
    int *p1 = ary1;
    int(*p2)[4] = &ary1;

    
    int nAry[2][4] = {
    
        {
    10,20,30,40},
        {
    60,70,80,90}
    };
    int(*p3)[4] = nAry;
    int (*p4)[2][4] = &nAry;

    return 0;
}

5、 ... and 、 A function pointer

The function pointer stores the address of the function . The name of the function is the address of the function ,& The value of the function name is also the address of the function .

void test(int n)
{
    
    printf("test:%d\r\n", n);
}

int main(int argc, char* argv[])
{
    
	//  Function name  = & Function name  =  Function address 
    printf("%p\r\n", test);
    printf("%p\r\n", &test);
    return 0;
}

5.1 Function pointer definition and call

void test(int n)
{
    
    printf("test:%d\r\n", n);
}

int main(int argc, char* argv[])
{
    
    //  Define function pointer variables pfun
    void (*pfun)(int n); 
    
    //  Function pointer variable assignment 
    pfun = test; 
    pfun = &test;
    
    //  Call the function saved by the function pointer 
    pfun(1); 
    (*pfun)(100);
    return 0;
}

The defined function pointer variable should have been written in this way void(*)(int n) pfun;, With a return value 、 Pointer to parameter , It's just that the grammar doesn't support this kind of writing .

But you can use typedef Rewrite the above definition ,typedef You can define a function pointer as a type .

typedef void(*PFUN)(int n);

int main(int argc, char* argv[])
{
    
    PFUN pfun = test;
    (*pfun)(100);
    return 0;
}

typedef Is equivalent to void(*)(int n) Name it PFUN.


Look at the code below :

(*(void(*)())0)();

The meaning of this code is , call 0 The code at the address . First of all, will 0 Convert to function function pointer void(*)() No parameter, no return value type , And then call the function. . The code is essentially a function call .

It is worth mentioning that there are two ways to call function pointers , Recommended (*pfun)(); This way of calling , Another way pfun() In some cases it may not be possible to use , As called above 0 The code at the address .


5.2 A function whose return value is a function pointer

Look at the code below :

void (*signal(int, void(*)(int n)))(int n);

The meaning of this code is to define a return value that is void(*)(int n) type , One of the parameters is int type , For another void(*)(int n) Function of type . It is essentially a function definition .

Since the above code is essentially a function definition , So how to write a function pointer to this function ?

void (*(*signal)(int, void(*)(int n)))(int n);

For the function pointer defined above , First (*signal) Is a function pointer ,void(*)(int n), Is the return value of the function and also a function pointer , The argument to this function is (int, void(*)(int n)).

Use typedef The code can be rewritten as :

typedef void(*PFUN)(int n);

int main(int argc, char* argv[])
{
    
    //void (*signal(int, void(*)(int n)))(int n);

    PFUN signal(int, PFUN);
    return 0;
}

It also shows that , When defining a function whose return value is a function pointer , In writing , You need to write the function parameters immediately after the function name , As above (int, void(*)(int n)). The return value of the function is just outside the parentheses that enclose the function name and parameters – A function pointer .

5.3 Function pointer array

Arrays hold the same type of data , When the data type is a function pointer , It becomes an array of function pointers , The definition is as follows :

int add(int a, int b)
{
    
    return a + b;
}

int sub(int a, int b)
{
    
    return a - b;
}

int main(int argc, char* argv[])
{
    
    int (*pfun[2])(int a, int b);
    pfun[0] = add;
    pfun[1] = sub;

    return 0;
}

Use typedef To rewrite :

typedef int(*PFUN)(int a, int b);

int main(int argc, char* argv[])
{
    
    PFUN pfun[2] = {
     add, sub };
    return 0;
}

Two ways to call functions :

int sum1 = pfun[0](1, 2);
int sum2 = (*pfun[0])(1, 2);

5.4 Array pointer of function pointer array

int (*pfun[2])(int a, int b);

typedef int(*PFUN)(int a, int b);
PFUN pfun[2] = {
     add, sub };

For function pointer arrays , The type of array name is array number 0 Pointer constants for elements , The... In the function pointer array 0 The types of the elements are PFUN, namely int(*)(int a, int b). Analogy of one-dimensional array and its function pointer , Arrays can be received with pointers , So there is the following code :

int main(int argc, char* argv[])
{
    
    PFUN pfun[2] = {
     add, sub };
    PFUN* pPfun = pfun;
    return 0;
}

Here is another way to write :

int main(int argc, char* argv[])
{
    
    int(*pfun[2])(int a, int b);

    int(**pPfun)(int a, int b) = pfun;
    return 0;
}

First, the element type in the function pointer array is int(*)(int a, int b), Its pointer type is int(**)(int a, int b)


about & Function pointer array , Variable of a certain type & Operation to get pointers of the same type , The type of function pointer array is PFUN[2], That is to say int(*[2])(int a, int b);

int main(int argc, char* argv[])
{
    
    PFUN pfun[2] = {
     add, sub };
    
    PFUN(*ppp2)[2] = &pfun;
    
    return 0;
}

Another way of writing :

int main(int argc, char* argv[])
{
    
    int(*pfun[2])(int a, int b);

    int(*(*pPfun)[2])(int a, int b) = &pfun;

    return 0;
}

First int(*[2])(int a, int b) Is the type of function pointer array , Its pointer int(*(*pPfun)[2])(int a, int b).

6、 ... and 、 summary

*(arr + n) = arr[n]

The type of array name is array number 0 Pointer constants for elements

Variable of a certain type & Operation to get pointers of the same type

7、 ... and 、 practice

C Language array and pointer exercises

原网站

版权声明
本文为[shlyyy]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/162/202206110242500103.html