Посмотр рубрик

Память, массивы

stdlib.h #

Динамическая память #

Уроки по использованию этих функций:

malloc #

void* malloc(size_t size)
Выделить в динамической памяти size байт. Вернёт отличный от нуля указатель, если память удалось выделить.

calloc #

void* calloc(size_t num, size_t size)
Выделить в динамической памяти num элементов размером size байт каждый и инициализировать нулями. Вернёт отличный от нуля указатель, если память удалось выделить.

realloc #

void* realloc(void* ptr, size_t size)
Изменить размер блока памяти по указателю ptr на size байт. Блок может остаться на месте или переехать, старые данные сохранятся до меньшего из двух размеров. При ошибке вернётся нулевой указатель, а старый блок останется действительным, поэтому результат обычно сначала записывают во временный указатель.

free #

void free(void* ptr)
Освободить память по указателю ptr. При нулевом указателе ничего не произойдёт.

Сортировка и поиск #

qsort #

void qsort(void* arr, size_t len, size_t size, int (*compare)(const void* a, const void* b))
Сортирует массив arr, состоящий из len элементов любого типа размером size каждый. compare - внешняя функция сравнения вида int func(const void* a, const void* b), которая должна возвращать:

  • -1 (любое отрицательное), если a < b
  • 0, если a == b
  • 1 (любое положительное), если a > b
// внешняя функция сравнения
int compare(const void* a, const void* b) {
    // сортировка по возрастанию
    return (*(int*)a - *(int*)b);

    // безопасная сортировка по возрастанию без переполнения
    // int av = *(const int*)a;
    // int bv = *(const int*)b;
    // return (av > bv) - (av < bv);
}

int main() {
    int arr[] = {51, 68, 23, 45, 18, 64, 72, 64, 26, 48};           // подопытный массив

    // вариант с внешней функцией
    qsort(arr, sizeof(arr) / sizeof(int), sizeof(int), compare);    // sizeof(arr) / sizeof(int) - кол-во элементов
    // arr == {18, 23, 26, 45, 48, 51, 64, 64, 68, 72}

    // вариант с лямбда-функцией
    qsort(arr, sizeof(arr) / sizeof(int), sizeof(int), [](const void* a, const void* b) -> int {
        // сортировка по убыванию
        return (*(int*)b - *(int*)a);

        // безопасная сортировка по убыванию без переполнения
        // int av = *(const int*)a;
        // int bv = *(const int*)b;
        // return (bv > av) - (bv < av);
    });
    // arr == {72, 68, 64, 64, 51, 48, 45, 26, 23, 18}
}

bsearch #

void* bsearch(const void* key, const void* arr, size_t num, size_t size, int (*compare)(const void* a, const void* b))
Быстрый поиск (бинарный, методом половинного деления) значения key в отсортированном массиве arr, состоящем из len элементов любого типа размером size каждый. Вернёт указатель на найденный элемент в массиве (если их несколько - на один из них), либо нулевой указатель, если элемент не найден. compare - внешняя функция сравнения вида int func(const void* a, const void* b), которая должна возвращать:

  • -1 (любое отрицательное), если a < b
  • 0, если a == b
  • 1 (любое положительное), если a > b
// внешняя функция сравнения
int compare(const void* a, const void* b) {
    return (*(const int*)a - *(const int*)b);
}

int main() {
    int arr[] = {18, 23, 26, 45, 48, 51, 64, 64, 68, 72};       // подопытный массив

    // вариант с внешней функцией
    int val1 = 51;
    int* res1 = (int*)bsearch(&val1, arr, sizeof(arr) / sizeof(int), sizeof(int), compare);
    // res1 != NULL
    // *res1 == 51
    // (res1 - arr) == 5 - индекс в массиве

    // вариант с лямбда-функцией
    int val2 = 41;
    int* res2 = (int*)bsearch(&val2, arr, sizeof(arr) / sizeof(int), sizeof(int), [](const void* a, const void* b) -> int {
        return (*(const int*)a - *(const int*)b);
    });
    // res2 == NULL
}

string.h #

memset #

void* memset(void* arr, int value, size_t num)
Заполнить num байт в массие arr байтовым значением value, вернёт arr:

uint8_t arr[6];
memset(arr, 123, sizeof(arr));
// arr == {123, 123, 123, 123, 123, 123}

memset(arr + 3, 100, sizeof(arr) - 3);
// arr == {123, 123, 123, 100, 100, 100}

memcpy #

void* memcpy(void* dest, const void* src, size_t num)
Скопировать num байт из src в dest, возвращает указатель dest. Указанные блоки не должны пересекаться:

int src[] = {1, 2, 3};
int dest[3];
memcpy(dest, src, sizeof(src));
// dest == {1, 2, 3}

//memcpy(src + 0, src + 1, sizeof(int) * 2);    // пересекается!

memccpy #

void *memccpy(void *dest, const void *src, int val, size_t len)
Функция относится к POSIX и появилась в стандарте C только в C23, поэтому доступна не на всех embedded-платформах.

Копировать не более чем len байт из src в dest, остановиться при достижении значения val в src (val копируется в dest). Возвращает указатель на следующий за val байт в dest или нулевой указатель, если val не был найден:

uint8_t arr1[5] = {0, 1, 2, 3, 4};
uint8_t arr2[5] = {5, 6, 7, 8, 9};
uint8_t* p = (uint8_t*)memccpy(arr2, arr1, 2, 5);
// arr2 == {0, 1, 2, 8, 9}
// *p == 8

memmove #

void* memmove(void* dest, const void* src, size_t num)
Скопировать num байт из src в dest, возвращает указатель dest. Указанные блоки могут пересекаться:

int src[] = {1, 2, 3};
// записать цифры 2 и 3 (индексы 1 и 2) начиная с индекса 0
memmove(src + 0, src + 1, sizeof(int) * 2);
// src == {2, 3, 3}

memcmp #

int memcmp(const void* p1, const void* p2, size_t num)
Сравнить num байт между массивами p1 и p2. Вернёт:

  • 0 - массивы совпадают
  • < 0 - первый несовпадающий байт в p1 имеет меньшее значение, чем в p2
  • > 0 - первый несовпадающий байт в p1 имеет большее значение, чем в p2
int p1[] = {1, 2, 3};
int p2[] = {1, 2, 3};
memcmp(p1, p2, sizeof(int) * 3);    // 0

int p3[] = {1, 1, 3};
memcmp(p1, p3, sizeof(int) * 3);    // > 0

memchr, memrchr #

const void* memchr(const void* arr, int value, size_t num)
void* memchr(void* arr, int value, size_t num)
const void* memrchr(const void* arr, int value, size_t num)
void* memrchr(void* arr, int value, size_t num)
memchr является стандартной функцией, а memrchr - расширение GNU и доступна не везде.

Найти байт со значением value в массиве arr размером num. Вернёт указатель на найденный элемент, иначе вернёт нулевой указатель. memchr ищет с начала массива (слева направо), memrchr ищет с конца (справа налево):

uint8_t arr[] = {1, 2, 3};
uint8_t* p = (uint8_t*)memchr(arr, 2, sizeof(uint8_t) * 3);
// *p == 2
// (p - arr) == 1, индекс 1

p = (uint8_t*)memchr(arr, 10, sizeof(uint8_t) * 3);
// p == NULL

memmem #

void* memmem(const void* arr, size_t arrsize, const void* sub, size_t subsize)
memmem - расширение GNU, стандартные C и C++ её не требуют.

Найти в массиве arr длиной arrsize совпадение с массивом sub длиной subsize, считай поиск подстроки в строке. Вернёт указатель на первое вхождение или нулевой указатель, если подстрока не найдена:

uint8_t arr[] = {1, 2, 3, 4, 5, 6};
uint8_t sub[] = {3, 4};
uint8_t* res = (uint8_t*)memmem(arr, sizeof(arr), sub, sizeof(sub));
// (res - arr) == 2, совпадение с индекса 2 (значение 3)

Дополнительно #

Дополнительный контент доступен владельцам набора GyverKIT и по подписке, подробнее читай здесь. Блок содержит:

  • Тезисы, Вопросы, Задания

Полезные страницы #


(1 голос)
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Прокрутить вверх