2. Puntero

Con respecto a lo que es un puntero, puede consultar la columna C elemental 5. Publicación de blog de punteros y variables de puntero

Una variedad de punteros

Transferencia de parámetros de matriz unidimensional

Transferencia de parámetros de matriz bidimensional

Matriz de dos punteros

Tres punteros de función y funciones de devolución de llamada

Puntero de función

Llamar de vuelta

Matriz de punteros de cuatro funciones

Cinco preguntas comunes de la entrevista

Puntero de matriz

Puntero a la matriz, la variable de puntero almacena la dirección de la matriz 1

#include <stdio.h>
int main() {
    int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int(*ptr_int)[10] = &arr;
    printf("%d\n", ((int*)(ptr_int + 1))[-1]); 
    // 数组指针向后偏移一个单位就相当于偏移整个数组长度个单位量
    return 0;
}

Cabe señalar que: el puntero de la matriz desplazado hacia atrás una unidad es equivalente a la dirección desplazada por la cantidad total de unidades de longitud de la matriz

También es necesario tener en cuenta que los punteros de matriz deben usarse para la transferencia de parámetros de matriz:

Transferencia de parámetros de matriz unidimensional
#include <stdio.h>
void test(int arr[10], int size)//ok?
{
    for (int i = 0; i < size; ++i)
        printf("%d ", arr[i]);
    printf("\n");
}
void test1(int arr[], int size)//ok?
{
    for (int i = 0; i < size; ++i)
        printf("%d ", arr[i]);
    printf("\n");
}
void test2(int* arr, int size)//ok?
{
    for (int i = 0; i < size; ++i)
        printf("%d ", arr[i]);
    printf("\n");
}
void test3(int* arr_ptr[10], int size)//ok?
{
    for (int i = 0; i < size; ++i)
        printf("%d ", *arr_ptr[i]);
    printf("\n");
}
void test4(int** arr_ptr, int size)//ok?
{
    for (int i = 0; i < size; ++i)
        printf("%d ", *arr_ptr[i]);
    printf("\n");
}
int main()
{
    int arr[10] = { 0 };
    for (int i = 0; i < 10; ++i)
        arr[i] = i + 1;
    int* arr_ptr[10] = { 0 };
    for (int i = 0; i < 10; ++i)
        arr_ptr[i] = arr + i;
    test(arr, 10);
    test1(arr, 10);
    test2(arr, 10);
    test3(arr_ptr, 10);
    test4(arr_ptr, 10);
    return 0;
}

test~test2都是一维整形数组传参方式,int arr[元素个数]、int arr[]、 int* arr;

test3~4是整形指针数组的传参方式,int* arr_ptr[元素个数]、int* *arr_ptr;

Transferencia de parámetros de matriz bidimensional
#include <stdio.h>
void test1(int arr[3][5], int row, int column)//ok?
{
    for (int i = 0; i < row; ++i){
        for (int j = 0; j < column; ++j)
            printf("%d ", arr[i][j]);
        printf("\n");
    }
    printf("\n");
}
void test2(int arr[][5], int row, int column)//ok?
{
    for (int i = 0; i < row; ++i) {
        for (int j = 0; j < column; ++j)
            printf("%d ", arr[i][j]);
        printf("\n");
    }
    printf("\n");
}
//总结:二维数组传参,函数形参的设计只能省略第一个口的数字。
void test3(int* arr, int row, int column)//ok?
{
    for (int i = 0; i < row; ++i) {
        for (int j = 0; j < column; ++j)
            printf("%d ", (arr + i * 5)[j]);
        printf("\n");
    }
    printf("\n");
}
void test4(int* arr[5], int row, int column)//ok?
{
    for (int i = 0; i < row; ++i) {
        for (int j = 0; j < column; ++j)
            printf("%d ", (arr+i*5)[j]);
        printf("\n");
    }
    printf("\n");
}
void test5(int(*arr)[5], int row, int column)//ok?
{
    for (int i = 0; i < row; ++i) {
        for (int j = 0; j < column; ++j)
            printf("%d ", arr[i][j]);
        printf("\n");
    }
    printf("\n");
}
void test6(int** arr, int row, int column)//ok?
{
    for (int i = 0; i < row; ++i) {
        for (int j = 0; j < column; ++j)
            //printf("%d ", (arr + i * 5)[j]);
            printf("%d ", arr[i * 5][j]);
        printf("\n");
    }
    printf("\n");
}
int main() {
    int arr[3][5] = { 0 };
    for (int i = 0; i < 3; ++i)
        for (int j = 0; j < 5; ++j)
            arr[i][j] = i*5 + j;
    test1(arr, 3, 5);
    test2(arr, 3, 5);
    test3(arr, 3, 5);
    test4(arr, 3, 5);
    test5(arr, 3, 5);
    test6(arr, 3, 5);
    return 0;
}

Test1 ~ test6 puede completar el proceso de transferencia de parámetros de matriz bidimensional


Matriz de punteros

Matriz de punteros

#include <stdio.h>
int main() {
    int a=1, b=2, c=3, d=4;
    int* arr_ptr[4] = { &a, &b, &c, &d };
    for (int i = 0; i < 4; ++i)
        printf("%d\n", *arr_ptr[i]);
    return 0;
}

La matriz de punteros arr_ptr almacena punteros de tipo int *


Puntero de función y función de devolución de llamada

Puntero de función: puntero a función

Definir una función de comparación para dar forma a elementos.

int compare (const void arg1, const void arg2) { return (int ) arg1-
(int
) arg2;
}

Definir un puntero de función para comparar

int * ptr_func (const void * arg1, const void * arg2) = comparar;

Llamar de vuelta

Una función de devolución de llamada es una función llamada a través de un puntero de función. Si pasa un puntero de función (dirección) como parámetro a otra función, cuando este puntero se usa para llamar a la función a la que apunta, decimos que se trata de una función de devolución de llamada. La función de devolución de llamada no es llamada directamente por el implementador de la función, pero es llamada por otra parte cuando ocurre un evento o condición específica, y se usa para responder al evento o condición.

Regala una castaña:

El último parámetro de la función de clasificación rápida qsort definida en <stdlib.h> y <search.h> requiere la dirección de función de una función de comparación

qsort ((void *) argv, (size_t) argc, sizeof (char *), compare);

El primer parámetro de la función de clasificación rápida qsort es la primera dirección del espacio a ordenar, el segundo parámetro argc es el número de elementos, el tercer parámetro es el tamaño en bytes de un elemento y el tercer parámetro es el tamaño del elemento proporcionado por el usuario. Función de comparación

#include <stdio.h>
int compare(const void* arg1, const void* arg2) {
    return *(int*)arg1 - *(int*)arg2;
}
int main() {
    int (*ptr_func)(const void* , const void* ) = compare;
    int arr[] = { 4, 6, 3, 1, 9, 8, 5, 2 };
    int args = sizeof(arr) / sizeof(int);
    qsort((void*)arr, args, sizeof(int), ptr_func);
    for (int i = 0; i < args; ++i)
        printf("%d ", arr[i]);
    printf("\n");
    return 0;
}

Matriz de punteros de función

En términos sencillos, es una matriz de punteros de función

Avión pequeño BC6

Inserte la descripción de la imagen aquí

Modo de matriz de puntero de función:

#include <stdio.h>
void func1(){
    
    
    printf("     **     \n");
}
void func2(){
    
    
    printf("************\n");
}
void func3(){
    
    
    printf("    *  *    \n");
}
int main()
{
    
    
    void (*p[3])() = {
    
    func1, func2, func3};
    for(int i=0; i<3; ++i){
    
    
        p[i]();
        p[i]();
    }
    return 0;
}

Formato de definición de matriz de puntero de función: valor de retorno de función + (* nombre de matriz de puntero) + (lista de parámetros) + lista de inicialización


Preguntas comunes de la entrevista

Prueba escrita 1:
int main()
{
    int a[5] = { 1, 2, 3, 4, 5 };
    int *ptr = (int *)(&a + 1);
    printf("%d, %d" *(a + 1), *(ptr - 1));
    return 0;
}

// ¿Cuál es el resultado del procedimiento?

2, 5

Prueba escrita 2:

// A través del conocimiento de la alineación de la memoria, podemos calcular el tamaño de la prueba de estructura en 20

#include <stdio.h>
struct Test
{
    int Num;
    char  pcName;
    short sDate;
    char cha[2];
    short sBa[4];
}*p;
//假设p的值为0x100000。如下表表达式的值分别为多少? int main()
int main() {
    printf("%p\n", p + 0x1);
    printf("%p\n", (unsigned long)p + 0x1);
    printf("%p\n", (unsigned int*)p + 0x1);
    return 0;
}

p + 0x1, la dirección del puntero está compensada por una unidad, está compensada por el tamaño del byte de estructura 0x100014

(unsigned long) p + 0x1 se convierte primero a la fuerza en cuatro bytes de longitud sin firmar, sin importar si el truncamiento ocurre en una plataforma de 32 o 64 bits, el valor final es 0x100001

(unsigned int *) p + 0x1 Primero fuerce el puntero de estructura a un puntero entero sin signo, agregue uno, la dirección está compensada por cuatro bytes y finalmente: 0x100004

Pregunta de prueba escrita 3:
int main()
{
    int a[4] = { 1, 2, 3, 4 );
    int *ptrl = (int *)(&a + 1);
    int *ptr2 = ((int)a + 1);
    printf("%x,%x”, ptrl[-l], *ptr2); 
    return 0;
}

apagar:

4, 00000003 2

Prueba escrita 4:
#include <stdio.h> 
int main()
{
    int a[3][2] = { (0, 1), (2, 3), (4, 5) };
    int *p;
    p = a[0];
    printf("%d", p[0]);
    return 0;
}

1

Pregunta de prueba escrita 5:
int main()
{
    int a[5][5];
    int(*p)[4];
    p = a;
    printf( "%p,%d\n", &p[4][2]-&a[4][2], &p[4][2] - &a[4][2]);
    return 0;
}

& p [4] [2] - & a [4] [2] = -4 se convierte en complemento hexadecimal 10000… 100 11111… 011 11111… 100 = FFFFFFFC

FFFFFFFC, -4

Pregunta escrita 6:
#include <stdio.h>
int main() {
    int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int* ptrl = (int*)(&aa + 1);
    int* ptr2 = (int*)(*(aa + 1));
    printf("%d,%d", *(ptrl - 1), *(ptr2 - 1));
    return 0;
}

10,5

Pregunta de prueba escrita 7:
#include <stdio.h>
int main()
{
    char* a[] = { "work", "at", "alibaba"};
    char** pa = a;
    pa++;
    printf("%s\n", *pa);
    return 0;
}

a

Pregunta de prueba escrita 8:
#include <stdio.h>
int main() {
    char* c[] = { "ENTER","NEW","POINT","FIRST" };
    char **cp[] = {c + 3, c + 2, c + 1, c};
    char*** cpp = cp;
    printf("%s\n", **++cpp);
    printf("%s\n", *-- * ++cpp + 3);
    printf("%s\n", *cpp[-2] + 3);
    printf("%s\n", cpp[-1][-1] + 1);
    return 0;
}
POINT ER ST EW

** ++ cpp, la prioridad pre - ++ es mayor que *. Primero ++ cpp, cpp es la dirección, se convierte en la dirección del elemento c + 2, y dos ** para obtener la dirección del primer elemento de "PUNTO"

* - * ++ cpp, la prioridad pre - ++ es mayor que * y la pre-precedencia es mayor que *. ++ cpp, cpp guarda la dirección de c + 1, después de eliminar la referencia, obtenga la dirección del elemento c

* cpp [-2], [] tiene una prioridad más alta que *. cpp [-2], obtener c + 3 elemento, desreferenciar para obtener la primera dirección de "FIRST", +3 es ST

cpp [-1] [- 1] + 1. cpp [-1] obtiene la dirección del elemento c + 2, luego [-1] obtiene la primera dirección de "NUEVO", luego +1, obtiene EW


  1. La cantidad de la unidad de compensación es el tamaño de toda la matriz ↩︎

  2. Tenga en cuenta que printf ("0x% x", 4) es 0x4 ↩︎

Supongo que te gusta

Origin blog.csdn.net/qq_43808700/article/details/112666400
Recomendado
Clasificación