Работа с памятью

Последнее обновление: 13.01.2023

memset

Функция memset из заголовочного файла string.h позволяет инициализировать блок динамической памяти начальными значениями. Она имеет следующий прототип:

void *memset(void *destination, int value, size_t N);

Параметры

  • destination: указатель на блок выделенной памяти

  • value: значение, которым инициализуются значения в блоке выделенной памяти

  • N: размер блока выделенной памяти

Например, выделим блок памяти для 5 чисел типа int и инициализируем все байты нулями:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
	// выделяем блок памяти для 5 чисел int
	int m = 5; 					// количество элементов
	int n = m * sizeof(int);	// размер выделяемой памяти
	int *ptr = malloc(n);
	if (ptr)
	{
		// иницилизируем все байты нулями
		memset(ptr, 0, n);
		// проверяем инициализацию
		for (int i = 0; i < m; i++)
		{
 			printf("%d ", ptr[i]);
 		}
 	}
 	free(ptr);
	return 0;
}

Стоит отметить, что инициализируются не числа int, которые здесь составляют массив ptr, а каждый байт блока памяти.

memcpy

Функция memcpy копирует определенное количество байт из одного блока памяти в другой. Она имеет следующий прототип:

void* memcpy(void *destination, const void *source, size_t N );

Параметры

  • destination: указатель на блок памяти, в который копируем

  • source: указатель на блок памяти, из которого копируем

  • N: количество копируемых байтов

Например, скопируем 5 байт из одного блока памяти в другой:

#include <stdio.h>
#include <string.h>

int main(void)
{
 	char source[] = "Hello World";
	// копируем 5 байт
 	char destination[5];
 	memcpy(destination, source, sizeof destination);

 	// выводим скопированные байты
 	for (int i = 0; i < sizeof destination; i++)
 	{
 		printf("%c", destination[i]);
 	}
	return 0;
}

Стоит отметить, что указателя блока, в который копируются байты, может также указывать на блок динамически выделяемой памяти:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
 	char source[] = "Hello World";
	// копируем 5 байт
	int n = 5;
 	char *destination = malloc(n);
 	memcpy(destination, source, n);

 	for (int i = 0; i < n; i++)
 	{
 		printf("%c", destination[i]);
 	}
	free(destination);
	return 0;
}

Также стоит отметить, что блоки памяти для копирования данных не обязательно представляют блок объектов типа char, они могут быть предназначены для любых других типов, например, int:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
	// копируем 5 объектов типа int
	const int n = 5;
 	int numbers[] = {1, 2, 3, 4, 5};
 	int *destination = malloc(n * sizeof(int));
 	memcpy(destination, numbers, n * sizeof(int));

 	for (int i = 0; i < n; i++)
 	{
 		printf("%d ", destination[i]);
 	}
	free(destination);
	return 0;
}

Другой пример - копирование структур:

#include <stdio.h>
#include <string.h>

struct person
{
	char name[20];
	int age;
};

int main(void)
{
	struct person tom = {"Tom", 38};	// структура, которую копируем
	struct person someperson;	// структура, в которую копируем

 	memcpy(&someperson, &tom, sizeof(struct person));

 	printf("Name: %s\n", someperson.name);
 	printf("Age: %d\n", someperson.age);
	return 0;
}

Поскольку функция memcpy принимают указатели, то в примере выше в данную функцию передаются адреса структур.

Сравнение объектов. memcmp

Функция memcmp сравнивает определенное количество байт двух объектов. Она имеет следующий прототип:

int memcmp( const void* p1, const void* p2, size_t N );

Первый и второй параметры представляют указатели на блоки памяти, которые сравниваются. Последний параметр представляет количество байт блоков p1 и p2, которые сравниваются.

Функция возвращает 0, если N байтов обоих объектов равны.

Если первый несовпадающий байт первого блока памяти больше соответствующего байта из второго блока, то возвращается число больше 0.

Если первый несовпадающий байт первого блока памяти меньше соответствующего байта из второго блока, то возвращается число меньше 0.

Например, сравним два объекта структуры:

#include <stdio.h>
#include <string.h>

struct person
{
	char name[20];
	int age;
};

int main(void)
{
	struct person tom = {"Tom", 38};
	struct person tomas = {"Tom", 38};

 	int result = memcmp(&tom, &tomas, sizeof(struct person));
	if(result == 0)
	{
		printf("tom and tomas are equal \n");
	}
	else	
	{
		printf("tom and tomas are not equal \n");
	}
	return 0;
}

В данном случае сравниваем все байты обоих структур. Поскольку их значения равны, то функция memcmp возвратит 0.

Причем поскольку функция сравнивает последовательно соответствующие байты обоих объектов, а в структурах данные располагаются по порядку определения элементов, то может быть так, что окажутся равны объекты разных типов структур:

#include <stdio.h>
#include <string.h>

struct person
{
	char name[20];
	int age;
};

struct employee
{
	char name[20];
	int age;
};

int main(void)
{
	struct person tom = {"Tom", 38};
	struct employee tomas = {"Tom", 38};

 	int result = memcmp(&tom, &tomas, sizeof(struct person));
	if(result == 0)
	{
		printf("tom and tomas are equal \n");
	}
	else	
	{
		printf("tom and tomas are not equal \n");
	}
	return 0;
}

Здесь два объекта структур person и employee имееют одни и те же элементы и их значения. Соответственно функция memcmp возвратит 0, несмотря на то, что это разные структуры.

Еще один пример - сравненим массивы:

#include <stdio.h>
#include <string.h>

int main(void)
{
	int numbers1[] = {1, 2, 3, 4, 5};
	int numbers2[] = {2, 1, 3, 4, 5}; 

 	int result = memcmp(numbers1, numbers2, sizeof(numbers1));
	if(!result)
	{
		printf("arrays are equal \n");
	}
	else	
	{
		printf("arrays are not equal \n");
	}
	return 0;
}

Здесь массивы не равны, соответственно функция возвратит число, которое не равно 0.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850