Linux программирование в примерах
Функция
была первоначальной функцией в System V API для копирования блоков памяти; ее поведение для перекрывающихся блоков памяти не была подробно определена тем или иным способом. Для стандарта С 1989 г. комитет почувствовал, что это отсутствие определенности является проблемой, поэтому они придумалиmemcpy(). Для обратной совместимостиmemmove()была оставлена, причем поведение для перекрывающейся памяти было специально отмечено как неопределенное, а в качестве процедуры, корректно разрешающей проблемные случаи, была предложенаmemcpy().memmove()Какую из них использовать в своем коде? Для библиотечной функции, которая не знает, какие области памяти ей передаются, следует использовать
. Таким способом вы гарантируете, что не будет проблем с перекрывающимися областями. Для кода приложения, который «знает», что две области не перекрываются, можно безопасно использоватьmemmove().memcpy()Как для
, так и дляmemcpy()(как и дляmemmove()) буфер назначения является первым аргументом, а источник — вторым. Чтобы запомнить это, обратите внимание на порядок, который тот же самый, как в операторе присваивания:strcpy()dest = src;(Справочные страницы во многих системах не помогают, предлагая прототип в виде '
' и полагаясь на то, что текст объяснит, что есть что. К счастью, справочная страница GNU/Linux использует более осмысленные имена.)void *memcpy(void *buf1, void *buf2, size_t n)12.2.3. Сравнение блоков памяти:
memcmp()Функция
сравниваетmemcmp()байтов из двух произвольных буферов данных. Возвращаемое ею значение подобноcount: отрицательное, нулевое или положительное, если первый буфер меньше, равен или больше второго.strcmp()Вы можете поинтересоваться: «Почему бы не использовать для такого сравнения
?» Разница между двумя функциями в том, чтоstrcmp()не принимает во внимание нулевые байты (завершающий строку 'memcmp()'.) Таким образом,\0является функцией, которая используется, когда вам нужно сравнить произвольные двоичные данные.memcmp()Другим преимуществом
является то, что она быстрее типичной реализации на C:memcmp()/* memcmp --- пример реализации на С, НЕ для реального использования */int memcmp(const void *buf1, const void *buf2, size_t count) {const unsigned char *cp1 = (const unsigned char*)buf1;const unsigned char *cp2 = (const unsigned char*)buf2;int diff;while (count-- != 0) {diff = *cp1++ - *cp2++;if (diff != 0)return diff;}return 0;}Скорость может быть достигнута в результате использования специальных инструкций «блочного сравнения памяти», которые поддерживают многие архитектуры, или в результате сравнения единиц, превышающих байты. (Эта последняя операция коварна, и лучше оставить ее автору библиотеки.)
По этим причинам всегда следует использовать вашу библиотечную версию
вместо прокручивания своей собственной. Велика вероятность, что автор библиотеки знает машину лучше васmemcmp()12.2.4. Поиск байта с данным значением:
memchr()Функция
сходна с функциейmemchr(): она возвращает местоположение определенного значения внутри произвольного буфера. Как и в случаеstrchr()противmemcmp(), основной причиной для использованияstrcmp()является использование произвольных двоичных данных.memchr()GNU
используетwcпри подсчете лишь строк и байтов [124], и это позволяетmemchr()быть быстрой. Изwсв GNU Coreutils:wc.c257 else if (!count_chars && !count_complicated)258 {259 /* Использует отдельный цикл при подсчете лишь строк или строк и байтов -260 но не символов или слов. */261 while ((bytes_read = safe_read(fd, buf, BUFFER_SIZE)) > 0)262 {263 register char *p = buf;264265 if (bytes_read == SAFE_READ_ERROR)266 {267 error(0, errno, "%s", file);268 exit_status = 1;269 break;270 }271272 while ((p = memchr(p, '\n', (buf + bytes_read) - p)))273 {274 ++p;275 ++lines;276 }277 bytes += bytes_read;278 }279 }Внешний цикл (строки 261–278) читает блоки данных из входного файла. Внутренний цикл (строки 272–276) использует
для поиска и подсчета символов конца строки. Сложное выражение 'memchr()' сводится к числу оставшихся байтов между текущим значением p и концом буфера.(buf + bytes_read) - рКомментарии в строках 259–260 нуждаются в некотором объяснении. Вкратце, современные системы могут использовать символы, занимающие более одного байта в памяти и на диске. (Это несколько более подробно обсуждается в разделе 13.4 «Не могли бы вы произнести это для меня по буквам?».) Таким образом,
должна использовать другой код, если она различает байты и символы: этот код имеет дело со случаем подсчета байтов.wc12.3. Временные файлы
Временный файл является в точности тем, что звучит в его названии: файл, в котором при исполнении программы хранятся данные, которые больше не нужны после завершения программы.
читает со стандартного ввода, если в командной строке не указаны файлы или вы используете в качестве имени файла 'sort'. Тем не менее,-должна прочестьsortсвои входные данные, прежде чем сможет вывести отсортированные результаты. (Подумайте об этом немного, и вы увидите, что это так.) Когда читается стандартный ввод, данные должны быть где-то сохранены, прежде чемвсесможет их отсортировать; это отличное применение для временного файла.sortиспользует временные файлы также для хранения промежуточных результатов сортировки.sort