¡Hola a todos! Hace algún tiempo me estuve preparando para el concurso de modelos matemáticos y ya terminé. Date prisa y continúa ofreciéndote contenido en lenguaje C. Hoy les daré una explicación de la parte básica de los punteros.
Cuando hablamos de punteros en lenguaje C, en realidad estamos discutiendo un concepto muy importante, porque los punteros son uno de los núcleos del lenguaje C. Nos permiten acceder directamente a los datos en la memoria, lo cual es muy útil a la hora de escribir programas eficientes y flexibles. Echemos un vistazo más profundo al concepto y uso de punteros.
Tabla de contenido
1. Comprensión preliminar de los consejos
2. Punteros y tipos de punteros
3. El significado de los tipos de punteros
1. Causas de los punteros salvajes
①El puntero no está inicializado
② Acceso fuera de límites del puntero
③Libere el espacio señalado por el puntero
3. Operaciones relacionales sobre punteros.
1. ¿Qué es un puntero?
1. Comprensión preliminar de los consejos
Dos puntos clave para entender los punteros:1. Un puntero es el número de la unidad más pequeña en la memoria, es decir, la dirección.2. Los punteros mencionados en el lenguaje hablado normal generalmente se refieren a variables de puntero, que son variables utilizadas para almacenar direcciones de memoria.Resumen: Los punteros son direcciones. Los punteros en el lenguaje hablado generalmente se refieren a variables de puntero.
Variables de puntero:Podemos usar & (operador de dirección) para obtener la dirección de memoria real de la variable y almacenar la dirección en una variable, que es una variable de puntero.
#include<stdio.h>
int main()
{
int a = 7;//创建变量时,在内存里开辟的一篇空间
int* pa = &a;//这里我们对变量a,取出它的地址,可以使用&操作符
//a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量
//中,p就是一个之指针变量
return 0;
}
Resumen: las variables de puntero son variables que se utilizan para almacenar direcciones. (Los valores almacenados en punteros se tratan como direcciones)
2. El tamaño del puntero.
En lenguaje C, el tamaño de los punteros varía según la arquitectura de la computadora y el sistema operativo. Normalmente, el tamaño de un puntero está relacionado con la cantidad de bits de la computadora. En sistemas de 32 bits, el tamaño del puntero suele ser de 4 bytes (32 bits), mientras que en sistemas de 64 bits, el tamaño del puntero suele ser de 8 bytes (64 bits).
3. Resumen
- Los punteros se utilizan para almacenar direcciones y las direcciones identifican de forma única un espacio de direcciones.
- El tamaño del puntero es de 4 bytes en plataformas de 32 bits y de 8 bytes en plataformas de 64 bits.
2. Punteros y tipos de punteros
Las variables tienen diferentes tipos, enteras, de coma flotante, etc. ¿El puntero tiene un tipo?
Los punteros tienen:
char *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;
Como puede ver aquí, la definición de punteros es: escriba + * .de hecho:Un puntero de tipo char* se utiliza para almacenar la dirección de una variable de tipo char .El puntero de tipo corto* se utiliza para almacenar la dirección de la variable de tipo corto .El puntero de tipo int* se utiliza para almacenar la dirección de la variable de tipo int
A continuación, explore el significado de los tipos de punteros.
3. El significado de los tipos de punteros
El tipo de puntero determina cuánta autoridad tiene al eliminar la referencia al puntero (cuántos bytes se pueden manipular)
Por ejemplo: la desreferencia del puntero char* solo puede acceder a un byte, mientras que la desreferencia del puntero int* puede acceder a cuatro bytes.
1. Puntero + - entero
int main()
{
int n = 10;
char* pc = (char*)&n;
int* pi = &n;
printf("%p\n", &n);
printf("%p\n", pc);
printf("%p\n", pc + 1);
printf("%p\n", pi);
printf("%p\n", pi + 1);
return 0;
}
2.Desreferencia
Se puede ver que los valores de pc y pi son iguales, después de ejecutar *pc=0, solo se cambia el valor del primer byte.
Después de ejecutar *p=0, solo se cambia el valor de cuatro bytes.
4. Puntero salvaje
Concepto: un puntero comodín significa que la posición señalada por el puntero es desconocida (aleatoria, incorrecta y sin restricciones claras)
1. Causas de los punteros salvajes
①El puntero no está inicializado
int main()
{
int* pa;
*pa = 10;
return 0;
}
Incluso el compilador nos impide utilizar punteros no inicializados.
② Acceso fuera de límites del puntero
int main()
{
int arr[10] = { 0 };
int* p = arr;
for (int i = 0; i <= 11; i++)
{
*(p++) = i;
}
return 0;
}
Cuando el rango señalado por el puntero excede el rango de la matriz arr , p es un puntero salvaje: naturalmente, se informará un error.
③Libere el espacio señalado por el puntero
int* createInt() {
int num = 5;
int* ptr = #
return ptr;
}
int main() {
int* ptr = createInt();
printf("%d\n", *ptr); // 输出5,但是这是不安全的操作
// 在这之后,ptr成为了野指针,因为它指向的内存空间已经被释放
printf("%d\n", *ptr); // 未定义的行为,可能输出垃圾值或导致程序崩溃
return 0;
}
En el ejemplo anterior, la función
createInt()
crea una variable enteranum
, asigna su dirección a un punteroptr
y devuelve el puntero. Enmain()
la función, imprimimosptr
el valor señalado por el puntero y el resultado es 5. PerocreateInt()
una vez finalizada la función,num
finaliza el ciclo de vida de la variable y se libera el espacio de memoria que ocupa. En este momento, el punteroptr
aún conserva la dirección de memoria anterior y se convierte en un puntero salvaje. En operaciones de impresión posteriores, intentamos accederptr
al valor señalado por el puntero comodín. Esta es una operación insegura y puede provocar un comportamiento indefinido del programa.
5. Aritmética de punteros
1. Puntero + - entero
- La suma y resta de punteros de números enteros se refiere a la suma y resta de punteros, donde el número entero representa el desplazamiento que se suma o resta. Esta operación se utiliza normalmente para mover un puntero una cierta distancia para acceder a la ubicación de memoria a la que apunta el puntero.
- Las operaciones de suma y resta de puntero se basan en el tamaño del tipo de datos al que apunta el puntero. Por ejemplo, si un puntero apunta a una
int
variable de un tipo, agregar 1 al puntero hará que el puntero apunte a unaint
variable del siguiente tipo. De manera similar, disminuir el puntero en 1 hará que el puntero apunte a unaint
variable del tipo anterior.
#include<stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5 };
int* pa = arr;
for (int i = 0; i < 5; i++)
{
printf("%d ", *(pa++));
}
return 0;
}
2. Puntero - puntero
La operación puntero-puntero se refiere a restar dos punteros para obtener el desplazamiento entre ellos. Esta operación se suele utilizar para calcular la distancia entre dos punteros o el número de elementos.
A continuación podemos usar esto para simular e implementar la función strlen()
int my_strlen(char* pa)
{
char* start = pa;
while (*pa)
{
pa++;
}
return pa - start;
}
int main()
{
char arr[] = "hello";
printf("%d", my_strlen(arr));
return 0;
}
3. Operaciones relacionales sobre punteros.
==
: Determina si dos punteros son iguales. Si dos punteros apuntan a la misma dirección de memoria, son iguales y se devuelven1
; en caso contrario, se devuelven0
.!=
: Determina si dos punteros no son iguales. Si los dos punteros apuntan a direcciones de memoria diferentes, no son iguales y devuelven1
; en caso contrario, devuelven0
.>
: determina si un puntero es mayor que otro puntero. El tamaño del puntero se compara en función de la dirección de memoria señalada por el puntero. Si la dirección señalada por el primer puntero es posterior a la dirección señalada por el segundo puntero, entonces el primer puntero es mayor que el segundo puntero, devuelve1
; en caso contrario, devuelve0
.<
: determina si un puntero es más pequeño que otro puntero. El tamaño del puntero se compara en función de la dirección de memoria señalada por el puntero. Si la dirección señalada por el primer puntero está antes de la dirección señalada por el segundo puntero, entonces el primer puntero es más pequeño que el segundo puntero, devuelve1
; en caso contrario, devuelve0
.>=
: determina si un puntero es mayor o igual que otro puntero. Devuelve si el primer puntero es mayor que el segundo puntero o si los dos punteros son iguales1
; en caso contrario0
.<=
: determina si un puntero es menor o igual que otro puntero. Devuelve si el primer puntero es menor que el segundo puntero o si los dos punteros son iguales; en caso contrario,1
devuelve0
4.Atención
Se permite comparar un puntero a un elemento de matriz con un puntero a una ubicación de memoria después del último elemento de la matriz, pero no con un puntero a una ubicación de memoria antes del primer elemento.
6. Punteros y matrices
1. Un puntero es una variable que se utiliza para almacenar una dirección de memoria. Las variables de puntero pueden apuntar a cualquier tipo de datos, incluidas las matrices. A través de punteros, podemos acceder y manipular indirectamente los datos en la memoria.
2. Una matriz es una matriz que puede almacenar un conjunto de números. El tamaño de la matriz depende del tipo y la cantidad de elementos.
3. El nombre de la matriz es la dirección del primer elemento de la matriz y la dirección se puede colocar en una variable de puntero. Accediendo a elementos de una matriz a través de punteros
- Nombre de la matriz y puntero: en lenguaje C, el nombre de la matriz puede considerarse como un puntero al primer elemento de la matriz. Por ejemplo, para una matriz
int arr[5]
,arr
se puede considerar comoarr[0]
un puntero a. Por lo tanto, puede acceder a los elementos de la matriz mediante punteros, como*arr
el primer elemento de la matriz y*(arr + 1)
el segundo elemento de la matriz. - Además, las operaciones aritméticas de punteros también se pueden aplicar a nombres de matrices. Por ejemplo,
arr + 1
representa la dirección del segundo elemento de la matriz,arr + 2
representa la dirección del tercer elemento de la matriz. Esto se debe a que los elementos de la matriz se almacenan de forma contigua en la memoria.
int main()
{
int arr[] = { 1,2 };
int* pa = arr;
printf("%p\n", arr);
printf("%p\n", &arr[0]);
return 0;
}
Se puede ver que el nombre de la matriz generalmente representa la dirección del primer elemento de la matriz, pero hay dos excepciones:
1. sizeof (nombre de la matriz), el nombre de la matriz se coloca solo dentro de sizeof, el nombre de la matriz representa la matriz completa , y se calcula el tamaño de la matriz, y la unidad es la palabra Festival.
2.& Nombre de la matriz, el nombre de la matriz representa la matriz completa y se extrae la dirección de la matriz. La dirección de la matriz es la misma que la dirección del primer elemento de la matriz, pero el tipo y el significado son diferentes.
7. puntero secundario
Las variables de puntero también son variables. Las variables tienen direcciones. Entonces, ¿dónde se almacena la dirección de la variable de puntero?
Este es el puntero secundario.
int main()
{
int a = 10;
int* pa = &a;//一级指针
int** ppa = &pa;//二级指针
printf("%d\n", a);
**ppa = 0;//通过两次解引用来改变值
printf("%d\n", a);
return 0;
}
8. Matriz de punteros
Una matriz de punteros es una matriz, una matriz que almacena punteros.
Puede utilizar una matriz de punteros para simular una matriz bidimensional
int main()
{
int arr1[] = { 1,2,4,6 };
int arr2[] = { 7,2,4,4 };
int arr3[] = { 1,2,9,6 };
int* p[] = { arr1,arr2,arr3 };
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%d ", p[i][j]);
}
printf("\n");
}
return 0;
}
Los punteros son un concepto poderoso y complejo en lenguaje C. Al utilizar punteros, podemos acceder y modificar directamente los datos en la memoria, logrando operaciones de memoria flexibles y eficientes. Sin embargo, debe tener cuidado al utilizar punteros para evitar problemas de punteros nulos y salvajes. Espero que este artículo le ayude a comprender la parte del puntero del lenguaje C.