¿Cómo entiendes los punteros?
1. El concepto de puntero
Un puntero es una variable especial y el valor almacenado en ella se interpreta como una dirección en la memoria. Para comprender un puntero, debe comprender cuatro aspectos del puntero: el tipo de puntero, el tipo apuntado por el puntero, el valor del puntero o el área de memoria apuntada por el puntero y el área de memoria ocupada por el puntero. sí mismo. Explique por separado.
Primero declare algunos consejos como ejemplo:
int *ptr;?
char *ptr;?
int * * ptr;?
int (*ptr)[3];?
int *(*ptr)[4];?
2. /p>
Desde un punto de vista gramatical, siempre que se elimine el nombre del puntero en la declaración de declaración del puntero, la parte restante es el tipo de puntero. Este es el tipo de puntero en sí. Eche un vistazo a los tipos de cada puntero a continuación: ?
int *ptr; //El tipo de puntero es int *?
char *ptr; el puntero es char *?
int **ptr; //El tipo del puntero es int **?
int (*ptr)[3]; del puntero es int(*)[3] ?
int *(*ptr)[4]; //El tipo del puntero es int *(*)[4]?
3. El tipo señalado por el puntero
Cuando se accede al área de memoria señalada por el puntero a través de un puntero, el tipo señalado por el puntero determina cómo tratará el compilador el contenido de esa. área de memoria como. Desde un punto de vista sintáctico, solo necesita eliminar el nombre del puntero en la declaración de declaración del puntero y el declarador del puntero * a la izquierda del nombre, y lo que queda es el tipo señalado por el puntero. Por ejemplo:?
int *ptr; //El tipo señalado por el puntero es int?
char *ptr; //El tipo señalado por el puntero es char?
p>int **ptr; //El tipo señalado por el puntero es int *?
int (*ptr)[3] //El tipo señalado por el puntero es int(); [3 ]?
int *(*ptr)[4]; //El tipo al que apunta el puntero es int *()[4]?
En operaciones aritméticas con punteros El tipo al que apunta el puntero juega un papel importante. ?
El tipo de puntero (es decir, el tipo del puntero en sí) y el tipo al que apunta el puntero son dos conceptos. A medida que se familiarice cada vez más con C, descubrirá que dividir el concepto de "tipo" mezclado con punteros en dos conceptos: "tipo de puntero" y "tipo al que apunta el puntero" es uno de los puntos clave. para dominar los punteros.
5. Valor del puntero
El valor del puntero es el valor almacenado en el puntero mismo. Este valor será tratado por el compilador como una dirección, no como un valor general. En programas de 32 bits, el valor de todos los tipos de punteros es un entero de 32 bits, porque las direcciones de memoria en programas de 32 bits tienen 32 bits de longitud. ?
El área de memoria señalada por el puntero es un área de memoria que comienza desde la dirección de memoria representada por el valor del puntero y tiene una longitud de sizeof (el tipo señalado por el puntero). De ahora en adelante, cuando decimos que el valor de un puntero es XX, equivale a decir que el puntero apunta a un área de memoria con la dirección encabezada por XX, cuando un puntero apunta a una determinada área de memoria, equivale a; diciendo que el valor del puntero es esta área de memoria la primera dirección. ?
El área de memoria señalada por el puntero y el tipo señalado por el puntero son dos conceptos completamente diferentes. En el ejemplo 1, el tipo al que apunta el puntero ya existe, pero como el puntero no se ha inicializado, el área de memoria a la que apunta no existe o no tiene sentido. ?
6. El área de memoria ocupada por el puntero.
Cuánta memoria ocupa el puntero; simplemente use la función sizeof (tipo de puntero) para probarlo y lo sabrá.
En plataformas de 32 bits, el puntero ocupa 4 bytes de longitud.
El concepto de memoria ocupada por el puntero en sí es útil para determinar si una expresión de puntero es un valor l.
Información ampliada:
Operaciones aritméticas sobre punteros
Los punteros pueden sumar o restar un número entero. El significado de esta operación de punteros es diferente del significado de las operaciones numéricas ordinarias de suma y resta. Por ejemplo:?
Ejemplo 1:?
char a[20];?
int *ptr=a;?
..?
...?
ptr;?
En el ejemplo anterior, el tipo de puntero ptr es int* y el tipo. apunta es int , que se inicializa para apuntar a la variable entera a. En las siguientes 3 oraciones, el puntero ptr aumenta en 1.
El compilador lo maneja así: agrega sizeof(int) al valor del puntero ptr. En un programa de 32 bits, Se agregaron 4. Dado que la dirección está en bytes, la dirección señalada por ptr aumenta en 4 bytes desde la dirección original de la variable a hasta la dirección de dirección superior.
Dado que la longitud del tipo char es de un byte, resulta que ptr apunta a los cuatro bytes comenzando desde la unidad 0 de la matriz a, y ahora apunta a la unidad 4 comenzando desde la matriz a de cuatro. bytes.
Puedes usar un puntero y un bucle para recorrer una matriz, mira el ejemplo:?
Ejemplo 2:?
Este ejemplo cambia cada unidad en el matriz de enteros Suma 1 al valor. Dado que el puntero ptr se incrementa en 1 cada vez que se repite, se puede acceder a la siguiente unidad de la matriz cada vez que se repite. Mire el ejemplo nuevamente:?
Ejemplo 3:?
char a[20];?
int *ptr = a;?
...?
...?
ptr = 5;?
En este ejemplo, se agrega 5 a ptr y el compilador es Esto se hace así: Suma 5 veces sizeof(int) al valor del puntero ptr. En un programa de 32 bits, se suma 5 veces 4 = 20. Dado que la unidad de dirección es el byte, la dirección señalada por el ptr actual se compara con la dirección señalada por ptr después de sumar 5.
Se movió 20 bytes hacia la dirección superior. En este ejemplo, ptr antes de agregar 5 puntos a los cuatro bytes a partir de la unidad 0 de la matriz a. Después de agregar 5, ptr ya apunta fuera del rango legal de la matriz a. Aunque esta situación causará problemas en la aplicación, gramaticalmente está bien. Esto también refleja la flexibilidad de los punteros.
Si en el ejemplo anterior, ptr se resta por 5, entonces el proceso de procesamiento es similar, excepto que el valor de ptr se resta por 5 veces sizeof(int) y la dirección a la que apunta el nuevo ptr será mayor que la original. La dirección señalada por ptr se mueve 20 bytes hacia la dirección inferior. ?
Para resumir, después de agregar un número entero n a un puntero ptrold, el resultado es un nuevo puntero ptrnew. El tipo de ptrnew es el mismo que el tipo de ptrold. tipo señalado por ptrold mismo. El valor de ptrnew será n multiplicado por sizeof (el tipo señalado por ptrold) bytes mayores que el valor de ptrold.
Es decir, el área de memoria señalada por ptrnew se moverá n veces sizeof (tipo señalado por ptrold) bytes a una dirección más alta que el área de memoria señalada por ptrold. Después de restar un número entero n de un puntero ptrold, el resultado es un nuevo puntero ptrnew. El tipo de ptrnew es el mismo que el tipo de ptrold. El tipo señalado por ptrnew también es el mismo que el tipo señalado por ptrold.
El valor de ptrnew se reducirá n veces el tamaño de bytes (el tipo señalado por ptrold) en comparación con el valor de ptrold. Es decir, el área de memoria señalada por ptrnew será menor que. el área de memoria señalada por ptrold. La dirección de la dirección se mueve n veces el tamaño de (el tipo señalado por ptrold).
Materiales de referencia:
Enciclopedia Baidu: sugerencias