Advanced C language pointer

In the front, we know some basic situations of pointers:

        A pointer is a variable. The pointer we say verbally refers to the pointer variable, which is used to store the address;

        The size of the pointer is fixed, 4 bytes on 32-bit platforms and 8 bytes on 64-bit;

        The pointer has a data type, and the data type of the pointer determines the step size of the pointer when it is +- integer;

This article mainly discusses some advanced uses of pointers.

One, character pointer

        Among the pointer types, there is a pointer type called a character pointer (char*);

Let's look at these two cases:

char ch = 'w';    

char *pc = &ch;

*pc = 'w';

printf("%c", *pc);//w

In this case, w is printed directly;

char* pstr = "hello world.";//Is a string put into the pstr pointer variable here?

* pstr = 'w';   

printf("%s\n", pstr); 

What is this situation like?

        When you run it, you will find that the program crashes. This is because the above "hello world." is a read-only data area stored in memory , that is, this string constant cannot be modified. Usually, we have Constants, plus the const keyword to protect the constant from being modified.

In order to deepen the impression, let's take a look at a question like this:

#include <stdio.h>
//判断一下代码的结果是什么
int main()
{
    char str1[] = "hello bit.";
    char str2[] = "hello bit.";
    char *str3 = "hello bit.";
    char *str4 = "hello bit.";
    if(str1 ==str2)
         printf("str1 and str2 are same\n");
    else
         printf("str1 and str2 are not same\n");
       
    if(str3 ==str4)
         printf("str3 and str4 are same\n");
    else
         printf("str3 and str4 are not same\n");
       
    return 0;
}

        Here str3 and str4 point to the same constant string. C/C++ will store the constant string in a separate memory area. When several pointers point to the same string, they will actually point to the same memory. But using the same constant string to initialize different arrays will open up different memory blocks. So str1 and str2 are different, and str3 and str4 are the same.

When defining pointer variables, there is often a misunderstanding:

int * pa, pb;

        The original idea was to define a pointer pa and a pointer pb, but this definition is wrong. Only pa is a pointer, and pb is just a normal variable.

Looking at the following code:

typedef int* pint;

#define PINT int*

...

PINT pa, pb;

pint pc, pd;

        In this case, pa, pc, pd are pointer variables, and pb are ordinary variables. The define preprocessing is just a simple substitution, and there is no other way; and the typedef keyword is a new name for a type. In this way, Both pc and pd have become pointer types.

Second, the pointer array

        What is an array of pointers? An array of pointers is an array of pointers. For example, an array of integers stores some integers, and an array of characters stores characters, analogous to an array of pointers, which stores pointers.

 Define an array of character pointers:

char* arr[] = { "abcdef", "qwer", "zhangsan" };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
	printf("%s\n", arr[i]);
}

 The result is as follows: 

                 

Third, the array pointer

        An array pointer is a pointer, which represents a pointer to an array. We define int(*p)[10], it should be noted that [] has a higher priority than *, so add (). This definition: p and * are combined , indicating that this is a pointer, and then points to an array of size 10 ints, that is, this pointer points to an array of size 10 ints

 It should be noted that it points to the first address of the array, not the address of the first element of the array. Let's look at such a set of codes:

int arr[10] = { 0 };

printf("arr = %p\n", arr);

printf("&arr= %p\n", &arr);

printf("arr+1 = %p\n", arr+1);

printf("&arr+1= %p\n", &arr+1);

The result is:

        We found that the address printed by the array name and & array name is the same. But after adding 1 to them, arr is the size of skipping 4 bytes, and &arr is the size of skipping 4*10 bytes. We found that , In fact &arr and arr, although the value is the same, but the meaning is different. In fact, &arr represents the address of the array, not the address of the first element of the array. The address of the array +1, skipping the size of the entire array, so &arr The difference between +1 and &arr is 40.

Array pointers are generally used to pass more parameters in two-dimensional arrays. In order to distinguish them, we use one-dimensional arrays and two-dimensional arrays for comparison.

int arr[10] = {1,2,3,4,5,6,7,8,9,0};    

int (*p)[10] = &arr ;// Assign the address of the array arr to the array pointer variable p, but there is no need to be so troublesome, and it will not be written like this, here is just a comparison

printf("%d", **p);//*p means to get the address of the array, and get the content 1 in * once;

//printf("%d", *((*p + 0) + 0));//(*)

printf("%d", *(*p + 1));//2

        Define an array of size 10, define an array pointer, point to the array of size 10, and then &arr operation, get the address of the array. It should be noted that: arr is the address of the first element of the array , and p is a pointer , why not directly int(*p)[10] = arr? Here p is the address pointing to the array, arr is the address of the first element of the array, not the address of the array, the address of the array is &arr. Looking at the two-dimensional condition:

int arr[3][5] = { {1,2,3,4,5}, {6,7,8,9,0}, {11,12,13,14,15} };

int(*p)[5] = arr;
print(arr, 3, 5);
printf("\n");

for (int i = 0; i < 3; ++i)
{     for (int j = 0; j < 5; ++j)     {         printf("%d ", *(*(p + i) + j) );//p+i represents the address of the i-th row, at *, this row is taken out, at +j, it is the address of the j-th element, at *, this element is taken out     }     printf( "\n");




}

        Here arr is missing &, but still the same, arr is the address of the first element of the array, and the address of the first element of the two-dimensional array is the first row, which is also an array, then there is no need to add &, otherwise an error will be reported . In essence, if we compare the one-dimensional array above to a two-dimensional array, then its print is (*).

Fourth, function pointers

        A function pointer is a pointer to a function. The definition of Void (*pfun1)(); means that pfun1 is a pointer, the pointer points to a function, this function has no parameters, and the return value is void. Let's look at the following code:

#include void test()

{

        printf("hehe\n");

}

intmain()

{

        printf("%p\n", test);

        printf("%p\n", &test);

        return 0;

}

 The output is two addresses, which are the addresses of the test function. In fact, it doesn't matter if this & plus or not.

        The results are all 5, and the compiler does not report any errors or warnings, which means that they are equivalent. In essence, for the function name, the preceding & and * will be ignored, and the preceding & not adding or or *No difference. Let's look at this code next:

(*( void (*)())0)();//From <<C language traps and defects>>

         It means: cast 0 to a function pointer of void (*)() type, dereference it and then call the function with no parameters and return type void at address 0.

Five, function pointer array

        Store the address of the function in an array. Then this array is called an array of function pointers. We define an array of function pointers such as int(*p[10])(), which means: [] combined with p, indicating that p is a Array, add a *, indicating that it is an array of pointers, add a (), indicating that this is a function, the parameters of the function are no parameters, at the same time, int indicates that its return value is of type int.

        One purpose of the function pointer array is to use it as a transfer table. For example, we make a calculator with two operands, the code is as follows, can the code of the switch part be simplified? Yes, it can be done by using the function pointer array .

#include <stdio.h>
int add(int a, int b)
{
 return a + b;
}
int sub(int a, int b)
{
 return a - b;
}
int mul(int a, int b)
{
 return a*b;
}
int div(int a, int b)
{
 return a / b;
}
int main()
{
 int x, y;
 int input = 1;
    int ret = 0;
    do
   {
        printf( "*************************\n" );
        printf( " 1:add           2:sub \n" );
        printf( " 3:mul           4:div \n" );
        printf( "*************************\n" );
        printf( "请选择:" );
        scanf( "%d", &input);
        switch (input)
       {
        case 1:
              printf( "输入操作数:" );
              scanf( "%d %d", &x, &y);
              ret = add(x, y);
              printf( "ret = %d\n", ret);
              break;
        case 2:
              printf( "输入操作数:" );
              scanf( "%d %d", &x, &y);
              ret = sub(x, y);
              printf( "ret = %d\n", ret);
              break;
        case 3:
              printf( "输入操作数:" );
              scanf( "%d %d", &x, &y);
              ret = mul(x, y);
              printf( "ret = %d\n", ret);
              break;
        case 4:
              printf( "输入操作数:" );
              scanf( "%d %d", &x, &y);
              ret = div(x, y);
              printf( "ret = %d\n", ret);
              break;
        case 0:
                printf("退出程序\n");
 			  break;
        default:
              printf( "选择错误\n" );
              break;
       }
 } while (input);
    
    return 0;
}
//函数指针数组实现
#include <stdio.h>
int add(int a, int b)
{
       return a + b;
}
int sub(int a, int b)
{
       return a - b;
}
int mul(int a, int b)
{
       return a*b;
}
int div(int a, int b)
{
       return a / b;
}
int main()
{
     int x, y;
     int input = 1;
     int ret = 0;
     int(*p[5])(int x, int y) = { 0, add, sub, mul, div }; //转移表
     while (input)
     {
          printf( "*************************\n" );
          printf( " 1:add           2:sub \n" );
          printf( " 3:mul           4:div \n" );
          printf( "*************************\n" );
          printf( "请选择:" );
      scanf( "%d", &input);
          if ((input <= 4 && input >= 1))
         {
          printf( "输入操作数:" );
              scanf( "%d %d", &x, &y);
              ret = (*p[input])(x, y);
         }
          else
               printf( "输入有误\n" );
          printf( "ret = %d\n", ret);
     }
      return 0;
}

Six, a pointer to an array of function pointers (simple understanding)

        A pointer to an array of function pointers is a pointer, the pointer points to an array, and the elements of the array are function pointers. It is defined as follows:

void test(const char* str)

{

        printf("%s\n", str);

}

intmain()

{

        //function pointer pfun

        void (*pfun)(const char*) = test;

        //array of function pointers pfunArr

        void (*pfunArr[5])(const char* str);

        pfunArr[0] = test;

        //pointer to function pointer array pfunArr

        ppfunArr void (*(*ppfunArr)[10])(const char*) = &pfunArr;

        return 0;

}

Guess you like

Origin blog.csdn.net/Naion/article/details/122517808