Juega con la función de modificación de memoria - [lenguaje C]

En el último blog, aprendimos funciones de cadena y podemos realizar una serie de operaciones en algunas cadenas. A continuación, aprenderemos algunas funciones de modificación de la memoria (#inlcude<string.h>), veamos las funciones mempy, memmove y memcmp juntas.


Tabla de contenido

función mempcyEditar

función de movimiento de memoria

función memcmp


función mempcy

A través del prototipo de función, podemos ver que el valor de retorno y algunos tipos de parámetros de puntero son tipos void*, lo que significa que esta función no se limita a cadenas, sino que puede implementarse para matrices de enteros, matrices de estructura, etc., tamaño_t num parámetros La unidad es byte, porque el tipo del puntero anterior es void*, no conocemos el tipo de elemento de la matriz entrante, por lo que la unidad del tercer parámetro es byte y se pueden copiar muchos tipos de datos.

La función memcpy es una función para copiar un bloque de memoria.La función memcpy copia números de bytes de datos hacia atrás desde la posición de origen a la posición de memoria de destino.

1. Parámetros: El puntero de destino es recibir la dirección del primer elemento de un arreglo de cualquier tipo, que se utiliza como destino.

El puntero de origen también recibe el mismo tipo de variable de puntero, que se utiliza para copiar el contenido.

size_t num es el número de bytes a copiar.

2. Valor devuelto: devuelve el puntero del objetivo.

3. La función no se detiene en '\0' , la función no verifica la fuente en busca de caracteres nulos de terminación; siempre copia exactamente el número de bytes .

4. Si hay alguna superposición entre el origen y el destino, el resultado de la copia es indefinido.

 Siguiente referencia a la función memcpy:

int main(void)
{
	int arr1[] = {1,2,3,4,5,6,7,8,9,10};
	int arr2[20] = { 0 };
	memcpy(arr2, arr1, 40);
	int i = 0;
	for (i = 0; i < 20; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

Copie los 40 bytes del contenido de la memoria en arr1 a arr2. Hay 20 ceros en arr2, pero solo se copian 10 elementos en arr1, por lo que los primeros 10 elementos en arr2 serán sobrescritos por el contenido en arr1, el resultado es el siguiente: A continuación, simulamos la implementación de la función memcpy  :

模拟实现
void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(src && dest);
	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

int main(void)
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	my_mempy(arr2, arr1, 40);
	for (int i = 0; i < 20; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

Creamos una función my_memcpy, modelada a partir del prototipo de función memcpy para crear un prototipo de función personalizado. Debido a que el valor de retorno es el puntero del primer elemento de la matriz de destino, primero creamos un puntero void* para marcar la matriz de destino. Luego usa el ciclo while para asignar valores byte por byte. Debido a que la función memcoy puede apuntar a cualquier tipo de matriz, debemos convertir todos los punteros de tipo void* en punteros del tipo char* de unidad más pequeña, para que pueda ser compatible con todo tipo de matrices. Cuando se complete la asignación, agregue 1 al puntero (para punteros de tipo void*, no podemos realizar operaciones ++ en él, por lo que solo podemos escribirlo en la forma dest = (char*)dest + 1;). Cuando num-- llega a 0, prueba que todas las asignaciones se han completado, simplemente salga del ciclo y regrese al puntero original.

Estos son los resultados de nuestra carrera:

El mismo resultado que obtuvimos con la función memcpy originalmente.

A continuación tenemos otra pregunta, ¿podemos usar la función memcpy para copiarnos el contenido de una matriz? En pocas palabras: hay una matriz de enteros int arr1[] = {1,2,3,4,5,6,7,8,9,10}; 1, 2, 3, 4, 5 en arr1 Poner en la posición de 3, 4, 5, 6, 7?

int main(void)
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	
	memcpy(arr1 + 2,  arr1, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

Pensamos en el contenido final en arr1: 1,2,1,2,3,4,5,8,9,10 pero ¿cuál es el resultado?

 Entonces, ¿por qué es esto así?

Entonces, ¿qué debemos hacer para completar el contenido en este momento? ¡Esto se hace usando la función memmove! !


función de movimiento de memoria

 La función memmove es una función que moverá un bloque de memoria, copiando el valor del número de bytes desde la ubicación señalada por el origen al bloque de memoria señalado por el destino . La copia es como si se utilizara un búfer intermedio, lo que permite que el destino y el origen se superpongan.

1. El valor de retorno y los parámetros son los mismos que los de la función mempy, podemos consultar lo anterior para comprenderlo.

2. El tipo subyacente del objeto al que apuntan los punteros de origen y destino es irrelevante para esta función, el resultado es una copia binaria de los datos.
La función no verifica la fuente en busca de caracteres nulos finales; siempre copia exactamente el número de bytes .
Para evitar el desbordamiento, el tamaño de las matrices a las que apuntan los argumentos de origen y destino debe ser al menos el número de bytes .

3. La diferencia con memcpy es que el bloque de memoria de origen y el bloque de memoria de destino procesados ​​por la función memmove pueden superponerse. Si el espacio de origen y el espacio de destino se superponen, debe usar la función memmove para solucionarlo.

 A continuación, usemos la función memmove para completar el problema anterior:

int main(void)
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr1 + 2, arr1, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

 Completó la pregunta hace un momento sin problemas.

Ahora simulemos la implementación de la función memmove:

void* my_memmove(void* dest,const void* src, size_t num)
{
	void* ret = dest;
	if (dest < src)
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
		return ret;
	}
	else
	{
		while (num--)
		{
			*((char*)dest + num) = *((char*)src + num);
		}
	}
}


int main(void)
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	my_memmove(arr + 2, arr, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

 Cree una función my_memmove y siga el prototipo de memmove para completar los parámetros de la función personalizada. Pero, ¿cómo debemos completar el cuerpo de la función?

Solo usando la copia más básica de adelante hacia atrás, no puede obtener el resultado deseado.Si copia de atrás hacia adelante, puede obtener la matriz deseada. En el caso de la escritura, necesitamos copiar de adelante hacia atrás, así que te resumiré:

Así que calificamos la situación para completar el cuerpo de la función personalizada, cuando el puntero dest <puntero src, el contenido interior es el mismo que el contenido de my_memcpy. Cuando el puntero dest > puntero src, continuamos usando el ciclo while y copiamos de atrás hacia adelante para completar. Se puede acceder al puntero desde atrás hacia adelante agregando el número de nun bytes antes de cada desreferencia, mientras que la condición de juicio es num--, y el puntero también se puede mover al juzgar si ha terminado, matando dos pájaros con uno piedra. Finalmente, devuelva la dirección del primer elemento de la matriz de destino. La única diferencia con la función my_memcpy debe discutirse por separado.

El resultado de la operación es el siguiente:

 ¡La simulación de esta función está completa!

Para las dos funciones anteriores, habrá una pregunta aquí, si la función memmove puede hacer lo que puede hacer la función memcpy. Eso es seguro. ¡Así que el papel de la función memmove debe ser mayor que el de la función mempy! ! !


función memcmp

 La función memcmp compara dos bloques de memoria, que es algo similar a la función strcmp.Compara si las dos matrices son iguales y el valor devuelto es el mismo. Pero la diferencia es que memcmp puede comparar más tipos, esta función no dejará de comparar después de encontrar un carácter nulo, pero strcmp se detendrá.

PTR1

Un puntero a un bloque de memoria.

PTR2

Un puntero a un bloque de memoria.

número

El número de bytes a comparar.

Realiza una comparación byte a byte al comparar los datos almacenados en la memoria.

 Aquí hay un ejemplo usando la función memcmp:

int main(void)
{
	int arr1[10] = { 1,2,1,4,5,6 };
	int arr2[10] = { 1,2,257 };
	int ret = memcmp(arr1, arr2, 9);
	printf("%d\n", ret);

	return 0;
}

Compare si los primeros 9 bytes en arr1 y arr2 son iguales.

 El contenido de almacenamiento de los primeros 10 bytes en arr1

Los primeros 10 bytes en el contenido de la tienda arr2 

Debido a que estamos comparando los contenidos de los primeros 9 bytes, todos son iguales y el valor de salida debe ser 0;  si comparamos los primeros 10 bytes, la salida debe ser -1; 

Lo anterior es todo lo que entiendo de la función de modificación de memoria, ¡espero que me puedan dar valiosos consejos en el área de comentarios! 

Supongo que te gusta

Origin blog.csdn.net/m0_74755811/article/details/131739369
Recomendado
Clasificación