[Fundamentos del lenguaje C 10 - puntero (1)]


prefacio

Este artículo comienza el estudio del contenido relacionado con punteros, los contenidos principales incluyen:

  • que es un puntero
  • Punteros y tipos de punteros
  • puntero salvaje
  • aritmética de punteros
  • punteros y matrices
  • puntero secundario
  • matriz de punteros

1. ¿Qué es un puntero?

2 puntos para la comprensión del puntero:

  • Los punteros que generalmente se hablan en el lenguaje hablado generalmente se refieren a variables de puntero, que son variables utilizadas para almacenar direcciones de memoria.
  • Un puntero es el número de una unidad más pequeña en la memoria, es decir, una dirección

1.1 Variables de puntero

Podemos usar el & (operador de dirección) para sacar la dirección real de la memoria de la variable y almacenar la dirección en una variable, que es una variable de puntero:

int main()
{
    
    
	int a = 1;//在内存中开辟一块空间
	//a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量中,p就是一个指针变量
	int* pa = &a;//这里我们对变量a,取出它的地址,可以使用&操作符
	printf("%p\n", &a);
	printf("%p\n", pa);
	a = 10;
	printf("%p\n", &a);
	return 0;
}

Use la memoria y el monitoreo para ver los cambios en &a y pa:
inserte la descripción de la imagen aquí
vea la imagen a continuación:

  • &a es la dirección de la variable a: 0x00CFFEE0
  • pa es una variable puntero, el valor almacenado es la dirección de la variable a: 0x00CFFEE0

La variable a ocupa 4 bytes de espacio, en la siguiente figura se puede ver que la dirección de a ocupa 4 bytes en la memoria, almacenando 00 00 00 01

inserte la descripción de la imagen aquí
El número de columnas de visualización de la memoria se puede ajustar de acuerdo con uno mismo, 4 columnas significan 4 bytes seguidos, vea la figura a continuación:
inserte la descripción de la imagen aquí
reasigne 10 a a, el valor de la variable a cambia, pero la dirección permanece sin cambios.
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
Por lo tanto, variables de puntero, variables utilizadas para almacenar direcciones. (El valor almacenado en el puntero se trata como una dirección).

1.2 Un puntero es el número de una unidad más pequeña en la memoria

  • Un puntero es el número de una unidad más pequeña en la memoria, que es un byte
  • Después de un cuidadoso cálculo y ponderación por parte de expertos, se encuentra que es más apropiado dar un byte a una dirección correspondiente
  • Para una máquina de 32 bits, suponiendo que hay 32 líneas de dirección, luego suponiendo que cada línea de dirección genera un nivel alto (voltaje alto) y un nivel bajo (voltaje bajo) al direccionar, es (1 o 0), 32 direcciones El dirección generada por la línea es:
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001
...
11111111 11111111 11111111 11111111

La unidad de memoria más pequeña es un byte, y su dirección correspondiente se muestra en la siguiente figura:
inserte la descripción de la imagen aquí
Por lo tanto, una máquina de 32 bits tiene 2 direcciones elevadas a 32. Cada dirección identifica un byte, entonces podemos dar:

2^32 bytes == 2^32/1024 KB == 2^32/1024/1024 MB == 2^32/1024/1024/1024 GB == 4 GB

4 GB libres para direccionamiento. De la misma manera, una máquina de 64 bits, si se le dan 64 líneas de dirección, puede direccionar 8 GB de espacio.

  • En una máquina de 32 bits, la dirección es una secuencia binaria de 32 0 o 1, por lo que la dirección debe almacenarse en 4 bytes de espacio, por lo que el tamaño de una variable de puntero debe ser de 4 bytes.
  • En una máquina de 64 bits, hay 64 líneas de dirección y el tamaño de una variable de puntero es de 8 bytes para almacenar una dirección.
  • El puntero se usa para almacenar la dirección, y la dirección es la marca única de una parte del 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
int main()
{
    
    
	int a = 10;
	int* pa = &a;
	char ch = 'a';
	char* pc = &ch;
	printf("%d\n", sizeof(pa));//4
	printf("%d\n", sizeof(pc));//4
	return 0;
}

El ejemplo anterior muestra que no importa qué tipo de variable de puntero, su tamaño es de 4 bytes. Debido a que la dirección está representada por 32 bits 0 1, y la variable de puntero es la variable que almacena la dirección, necesita 4 bytes para almacenar. Independientemente de su tipo.
inserte la descripción de la imagen aquí

2. Punteros y tipos de punteros

Las variables tienen diferentes tipos, enteros, flotantes, etc. Ese puntero también tiene un tipo:

int num = 10;
p = #//num的地址保存到 p 

Para guardar &num (la dirección de num) en p, sabemos que p es una variable de puntero, entonces, ¿cuál es su tipo? Damos a la variable puntero el tipo correspondiente

char *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;

Los punteros se definen como: tipo + *

  • El puntero de tipo char* se usa para almacenar la dirección de la variable de tipo char: es decir, la variable en la dirección es de tipo char, ocupando 1 byte, y la dirección en sí es de 4 bytes.
  • El puntero de tipo short* se utiliza para almacenar la dirección de la variable de tipo short: es decir, la variable en la dirección es de tipo short, ocupando 1 byte, y la dirección en sí es de 4 bytes.
  • El puntero de tipo int* es para almacenar la dirección de la variable de tipo int: es decir, la variable en la dirección es de tipo int, ocupando 4 bytes, y la propia dirección es de 4 bytes

2.1 Puntero±Tipo

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;
}

El tipo del puntero determina qué tan lejos (distancia) el puntero avanza o retrocede:

  • int * +1 hacia atrás, es moverse a la dirección de la siguiente variable de la clase int, es moverse 4 bytes
  • char * +1 hacia atrás, es moverse a la dirección de la siguiente variable de tipo char, es moverse 1 byte
  • El tipo del puntero, que es el tipo del valor almacenado en el puntero a la dirección.

inserte la descripción de la imagen aquí

2.2 Desreferencia de punteros

El tipo de puntero determina cuánta autoridad tiene al desreferenciar el puntero (puede operar en unos pocos bytes)

2.2.1 Desreferencia de tipos int*

int main()
{
    
    
	int a = 0x11223344;
	int* pa = &a;
	*pa = 0;
	return 0;

Eliminar la referencia de un puntero a un int * da acceso a cuatro bytes :
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

2.2.2 Desreferencia del tipo char*

int main()
{
    
    
	int a = 0x11223344;
	char* pa = (char*)&a;//&a是int*,所以在这里强制转换
	*pa = 0;

	return 0;
}

Una desreferencia de puntero a char * solo puede acceder a un byte :

inserte la descripción de la imagen aquí

inserte la descripción de la imagen aquí

3. Puntero salvaje

Un puntero salvaje es donde el puntero apunta es desconocido (aleatorio, incorrecto, no especificado)

3.1 Causas de los punteros salvajes

3.1.1 Puntero no inicializado

int main()
{
    
    
	int *p;//局部变量指针未初始化,默认为随机值
	*p = 20;
	return 0;
}

3.1.2 Acceso fuera de los límites del puntero

int main()
{
    
    
	int arr[10] = {
    
    0};
	int *p = arr;
	int i = 0;
	for(i=0; i<=11; i++)//超过数组的元数个数
	{
    
    
		//当指针指向的范围超出数组arr的范围时,p就是野指针
		*(p++) = i;
	}
	return 0;
}

3.1.3 Liberar el espacio señalado por el puntero

int* test()
{
    
    
	int a = 10;
	printf("%d\n", a);
	return &a;//开辟的空间已经释放了
}
int main()
{
    
    
	int* p = test();//函数调用结束后,开辟的内存空间释放了
	*p = 100;
	return 0;
}

3.2 Cómo evitar los punteros salvajes

  • inicialización del puntero
  • Cuidado con el puntero fuera de los límites
  • El puntero al espacio se libera incluso si se establece en NULL
  • Evite devolver la dirección de una variable local
  • Comprobar la validez del puntero antes de su uso
int main()
{
    
    
	int *p = NULL;//初始化
	//....
	int a = 10;
	p = &a;
	if(p != NULL)
	{
    
    
		*p = 20;
	}
	return 0;
}

Resumir

Este artículo ha aprendido parte del contenido de los punteros, y el próximo artículo continuará aprendiendo el contenido de los punteros.

Supongo que te gusta

Origin blog.csdn.net/taibudong1991/article/details/123788274
Recomendado
Clasificación