Estructura de datos del lenguaje C (3) - tipo de puntero

El puntero es la principal aplicación característica del lenguaje C. En el lenguaje C, el puntero es un tipo de datos básico, que se puede combinar con matrices, funciones, estructuras, etc., para ser utilizado en diversas ocasiones. Cuando aprendemos punteros, tenemos que hacer dos cosas: saber siempre hacia dónde apunta cada puntero; saber siempre a qué apunta el puntero.

punteros y variables de puntero

Antes de aprender los punteros, debemos averiguar el significado de las variables. Cada variable tiene dos significados físicos, uno es su propio contenido y el otro es la dirección de la variable. Podemos pensar en la memoria de la computadora como una fila de casas en una calle larga.Cada casa puede acomodar datos y se identifica con un número de casa. En este momento, los datos de la casa son el contenido de la variable en sí, y el número de habitación es la dirección de la variable. Una descripción más precisa debería ser:
el contenido de la variable son los datos almacenados por la variable en el espacio de almacenamiento asignado.
La dirección de una variable es la primera dirección del espacio de almacenamiento asignado por la variable.

Entonces tenemos que averiguar el acceso directo e indirecto . La operación de acceso a las variables en el programa es operar sobre varias unidades de almacenamiento de bytes en una determinada dirección. En general, solo se necesita señalar el nombre de la variable en el programa, y ​​no es necesario saber la dirección específica de cada variable en la memoria.La conexión entre cada variable y la dirección específica se completa con el sistema compilador C. Cuando se ejecuta el programa, la operación de acceso a la variable es en realidad la operación sobre la unidad de almacenamiento de una determinada dirección. Esta forma de acceder directamente al valor de la variable según la dirección de la variable se denomina "acceso directo". Por ejemplo, si el nombre de la variable entera a se cita en el programa, el sistema automáticamente accederá directamente al contenido de 4 bytes de la variable a según el valor de dirección de a.
Si se define una variable especial, esta variable se utiliza especialmente para almacenar la dirección de memoria, que se denomina variable puntero, como se muestra en la figura, supongamos que definimos una variable pa, que también tiene su propia dirección 2004; si la dirección de la variable a (1001) se almacena en la variable pa. En este momento, para acceder a la unidad de almacenamiento representada por la variable a, primero puede encontrar la dirección de memoria de pa (2004), sacar la dirección de a (1001) desde allí, y luego vaya a acceder a la dirección encabezada por la unidad de almacenamiento 1001. Este método de obtener indirectamente la dirección de la variable a a través de la variable pa y luego acceder al valor de a se denomina "acceso indirecto".
inserte la descripción de la imagen aquí

Después de descubrir los dos conceptos anteriores, podemos aprender punteros más fácilmente.¿Qué es un puntero? ——Un puntero es una "dirección", y la dirección de una variable se llama puntero. Como tipo de datos, los punteros también se pueden dividir en constantes de puntero y variables de puntero, y sus variables tienen el mismo significado que otros tipos de variables. Deben definirse antes de poder calcularse u operarse. El valor de una variable de puntero debe ser la dirección de una variable.
Si la variable de puntero ya tiene un valor de dirección, se puede decir que la variable de puntero apunta a una determinada variable, y la variable a la que apunta la variable de puntero se denomina variable de destino. Por ejemplo: la variable apuntadora pa establece una relación de apuntamiento con la variable a a través de pa=&a, llamamos a la variable apuntadora pa apuntando a la variable a, y la variable a es la variable objetivo de la variable apuntadora pa.

Nota : El tipo del puntero y el tipo al que apunta el puntero son dos conceptos. El tipo de un puntero es el tipo del propio puntero, y el tipo al que apunta el puntero es el tipo de la variable a la que apunta el puntero. Por ejemplo:

int a=5,b;
float x;
int *pi;
float *pf;

Entre ellos: el tipo del puntero pi: int *, el tipo del puntero pf: float *, el tipo al que apunta pi: int, el tipo al que apunta pf: float.

Definición de variable puntero

La forma de definición general de una variable de puntero:

Tipo de datos* nombre de variable de puntero
Entre ellos: " * " indica que el siguiente nombre de variable es un tipo de puntero; "tipo de datos" es el tipo de datos que define la variable de destino a la que apunta la variable de puntero, y también se puede llamar la base tipo de la variable puntero.

Inicialización de variables de puntero

A las variables puntero también se les pueden asignar valores iniciales cuando se definen como otros tipos de variables.La forma general es:
tipo de dato * nombre de la variable puntero = valor de dirección inicial

#include <stdio.h>
void main()
{
    
    
	float x,*p1=NULL,*p2=&x;
	int y,*p3=&y;
	char name[30],*cp=name;
	...
}

Como se muestra arriba, haga que p1 sea un puntero nulo, y p2, p3 y cp almacenen respectivamente la dirección de x, la dirección de y y la primera dirección de la matriz de nombres. Se puede decir que p2 apunta a x, p3 apunta a y, y cp apunta a nombre[0].
Nota : 1. Al asignar la dirección de una variable como el valor inicial del puntero, primero se debe definir la variable y el tipo de datos de la variable debe ser coherente con el tipo de datos del puntero.

int n;
int *p=&n;

o con la siguiente definición equivalente

int n,*p=&n;

2. También puede asignar un valor de puntero inicializado como valor inicial a otro puntero

float x,*p=&x,*q=p;

Tanto p como q tienen el mismo valor de dirección, ambos apuntan a la misma variable x.
3. Un cierto tipo de puntero nulo también se puede definir mediante la inicialización

int *p=0;/*值0是唯一能够直接付给指针变量的整型数*/
int *p=NULL;

Las dos líneas de código anteriores tienen el mismo efecto y ambas definen un puntero nulo.

Operaciones básicas con punteros

1. La operación de dirección
& requiere que la variable de operación sea una variable o un elemento de matriz, y devuelve la dirección que apunta a la variable o elemento de matriz. La forma general es:
& nombre de variable o nombre de elemento de matriz

int a,*p;
pa=&a;

La implementación asigna la dirección de la variable al puntero pa, y el puntero pa apunta a la variable entera a en este momento.
2. Operación de acceso indirecto
El operador de acceso indirecto "*" generalmente se denomina "operación de acceso indirecto", que es un operador unario; su operando derecho debe ser un valor de puntero y el valor de retorno es el valor de su dirección especificada. La forma general es:
* La dirección de una variable de puntero o variable de destino

int a,b,*p;
pa=&a;
b=*pa;

El operador "*" accede al área de almacenamiento con la dirección de pa, y la dirección de la variable a se almacena en pa, por lo que la dirección a la que accede *pa es la dirección de inicio de la variable a, que es el área de almacenamiento ocupada por a, todas las anteriores La expresión de asignación para es equivalente a b=a.

Se puede ver que el operador "&" y el operador "*" son operaciones inversas. Preste atención para distinguir los diferentes significados de las siguientes expresiones diferentes:
pa——variable de puntero
*pa——la variable de destino del puntero pa
&pa——variable de puntero pa ocupa la dirección del área de almacenamiento
3. Operación de asignación
(1) asignar el dirección de una variable a un mismo tipo de puntero, como por ejemplo:

int  a, *pa;
pa=&a; 		/* 使pa指向变量a */

(2) Asignar el valor de un puntero a otro puntero del mismo tipo, como por ejemplo:

char  c, *s1=&c, *s2;
s2=s1;      /* 结果s1和s2指向同一变量c */

(3) Asigne constantes de dirección, como nombres de matriz, a punteros del mismo tipo, como:

char  *str,ch[80];
str=ch;      /* 使str得到字符数组ch的首地址,即str指向数组ch */

(4) El resultado de la operación aritmética sobre punteros del mismo tipo, si todavía es una dirección, puede asignarse a un puntero del mismo tipo. Por ejemplo:

int *p1,*p2,a[20];
p1=a;  p2=p1+5;  p1=p2-3

La diferencia entre la asignación de valor inicial y la operación de asignación: la asignación de valor inicial es asignar un valor a la variable mientras se define la variable, no una operación de acceso indirecto. El resultado de una operación de acceso indirecto es una variable entera que no puede recibir un valor de dirección.

4. Operaciones aritméticas con punteros
(1) Sumar o restar un número entero del puntero

int a[10],*pa=a,*p;
pa+=5;/*pa指向变量a[5]*/
pb=pa-3;/*pa指向变量a[2]*/

(2) Se restan dos punteros del mismo tipo

int a[10],*pa=&a[1],*pb=&a[8];
int dist;
dist=pb-pa;/*diat为7,表明pa与pb两个指针所指向的数组元素之间的距离*/

Puntos clave de la suma y resta de punteros:
① No se pueden sumar dos variables de puntero.
② La suma y resta de punteros tiene sentido solo cuando la variable del puntero apunta a una matriz, y solo cuando el resultado de la operación todavía apunta a un elemento en la misma matriz.
③ El resultado de la suma y resta de punteros no está en bytes, sino en el tamaño del tipo de datos (es decir, tamaño de (tipo)).
④ Solo cuando dos variables de puntero apuntan a la misma matriz, es práctico realizar la resta de puntero.
⑤ *(p1+n) y (*p1)+n son dos conceptos diferentes.
5. Operación relacional de punteros
(1) Las operaciones relacionales se pueden realizar en dos punteros que apuntan a la misma matriz
(2) No tiene sentido comparar un puntero con datos enteros, y la comparación entre variables de puntero de diferentes tipos es ilegal.
⑶ NULL puede realizar operaciones == y != con cualquier tipo de puntero para determinar si el puntero es un puntero nulo.

punteros y matrices

En el lenguaje C, la relación entre punteros y matrices es extremadamente estrecha. Al introducir arreglos, ya conocemos el método de almacenamiento de los elementos del arreglo en la memoria de la computadora y cómo se asignan las direcciones de los arreglos, y solo las operaciones aritméticas y las operaciones relacionales entre punteros que apuntan al mismo arreglo son significativas, por lo que la combinación de arreglos y punteros También hay muchas aplicaciones en lenguaje C.

Punteros y arreglos unidimensionales

1. Para crear un puntero a una matriz unidimensional, puede definirlo primero y luego asignar un valor al puntero. Por ejemplo:

int a[5],*pa,*p;
pa=a;/*  pa=&a[0];  */

Como el nombre del arreglo a es la primera dirección del arreglo, es decir, la dirección de a[0], el puntero pa apunta a la primera dirección del arreglo. En este momento, el valor de *pa es el valor de a[0]. pa+1 apunta al siguiente elemento. En casos especiales, también es posible hacer que el puntero apunte a un elemento de matriz directamente después de definir el puntero, como: p=&a[5]; 2. Hacer referencia a
un elemento de matriz a través de un puntero
Por lo general, hay tres formas de se refieren a un elemento de matriz:
(1) método de subíndice, como la forma de a[i];
(2) método de dirección de nombre de matriz, ya que el nombre de matriz es la primera dirección de la matriz, de acuerdo con la regla de cálculo de la dirección , entonces a+i significa la primera dirección a partir del nombre de matriz a i elementos, es decir, la dirección de a[i], luego *(a+i) es a[i] (3) Método de puntero, hay
dos formularios
①Método de dirección de puntero. Dado que hay pa=a, entonces pa+i significa el i-ésimo elemento que comienza en pa, es decir, la dirección de a[i], entonces *(pa+i) es a[i] ② Método estándar de puntero hacia abajo
. Dado que pa=a, *(pa+i) es equivalente a a[i], entonces la forma de pa[i] puede usarse directamente en lenguaje C para representar los i-ésimos datos del mismo tipo a partir de la posición indicada por pa.

En resumen: para el puntero pa del mismo tipo de dato y el arreglo a, una vez establecida la relación pa=a entre ambos (es decir, el puntero pa apunta a la primera dirección del arreglo a), entonces se cumple lo siguiente para el elemento de matriz a[i] La representación es equivalente:
a[i], * (a+i), * (pa+i), pa[i]

Preste atención cuando use el método del puntero para acceder a los elementos de la matriz:
(1) El valor de la variable del puntero se puede cambiar, pero el valor de la constante del puntero utilizada como nombre de la matriz no se puede cambiar. Si a es un nombre de matriz, p es un puntero y b es una variable, es incorrecto intentar cambiar el valor de a, pero el puntero es una variable de dirección y su valor se puede cambiar.
(2) Cuando se usan variables apuntadoras para acceder a los elementos de la matriz, se debe considerar el problema de la matriz fuera de los límites
(3) Si se usan variables apuntadoras en la representación de subíndices de los elementos de la matriz, sus subíndices pueden tener valores negativos. Si hay un puntero p y una matriz b, cuando p=&b[2], si el elemento b[1] necesita usar la variable de puntero p, la notación de subíndice es p[-1] y el método de puntero es * (p-1)
(4) Debe prestarse especial atención a la correcta asociatividad de los operadores unarios en las operaciones con variables apuntadoras. Por ejemplo, y=* p++ es equivalente a y=* (p++), y=* ++p es equivalente a y=*(++p)

Punteros y matrices 2D

Una matriz bidimensional es similar a una matriz unidimensional.Después de establecer la relación entre los punteros y las matrices, los punteros se pueden usar para representar los elementos de la matriz.
Ahora bien, si existe un arreglo a[3][4],
las formas de indicar elementos de fila son las siguientes:
a[0] se puede indicar con * (a+0), es decir, * a se puede usar para indicar que a[i] se puede indicar
con * (a+i) &a[1][3] se puede representar con a[1]+3 o * (a+1)+3 &a[i ][j] puede ser representado por a[i]+jo * (a+i)+j significa


Los elementos de matriz bidimensional se pueden representar de las siguientes maneras:
subíndice de matriz: a[i][j]
notación de puntero: * (* (a+i)+j)
notación de subíndice de número de fila: * (a[ i]+j )
notación de subíndice de número de columna: * (a+i)[j]

Resumir

Los punteros son una parte importante del lenguaje C y una característica principal del lenguaje C. Para aprender bien los punteros, debe aclarar los dos significados físicos de las variables, la dirección de la variable y el contenido de la variable. La variable puntero también tiene su dirección variable y contenido variable, pero el contenido variable de la variable puntero es el dirección de otros tipos de variables Al referenciar la variable puntero Es el contenido de la variable apuntada por la variable puntero de acceso indirecto. Al usar una variable de puntero, es necesario prestar atención al identificador "*", que tiene diferentes significados en diferentes situaciones. *p representa la variable de destino del puntero p, y &p representa la dirección del puntero p. Preste atención a la aplicación de la combinación de punteros y matrices, y la forma en que los punteros representan las matrices.

Supongo que te gusta

Origin blog.csdn.net/Tao_9/article/details/129836560
Recomendado
Clasificación