Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Linux ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ…Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 106

Автор ΠΡ€Π½ΠΎΠ»ΡŒΠ΄ Роббинс

Π­Ρ‚ΠΎΡ‚ случай ΠΏΠΎΠ΄Π½ΠΈΠΌΠ°Π΅Ρ‚ Π²Π°ΠΆΠ½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠ² ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ. Часто программисты ΠΎΡˆΠΈΠ±ΠΎΡ‡Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ вмСсто ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ ошибок Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ исполнСния. Π’ нашСм случаС тСст 'array != NULL' Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Π» Π±Ρ‹Ρ‚ΡŒ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΎΠΉ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ исполнСния:

if (array == NULL) return -1;

ВСст 'size > 0' (строка 13) ΠΌΠ΅Π½Π΅Π΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°Ρ‚ΠΈΡ‡Π΅Π½; Ссли size Ρ€Π°Π²Π΅Π½ 0 ΠΈΠ»ΠΈ мСньшС 0, Ρ†ΠΈΠΊΠ» Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ исполнится, ΠΈ lsearch() (ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ) Π²ΠΎΠ·Π²Ρ€Π°Ρ‚ΠΈΡ‚ -1. (По ΠΏΡ€Π°Π²Π΄Π΅, этот ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Π½Π΅ Π½ΡƒΠΆΠ΅Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΊΠΎΠ΄ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ случай 'size <= 0'.)

Π›ΠΎΠ³ΠΈΠΊΠ°, стоящая Π·Π° ΠΎΡ‚ΠΌΠ΅Π½ΠΎΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ, Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ ΠΌΠΎΠ³ΡƒΡ‚ ΡΠ½ΠΈΠ·ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈ поэтому Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ Π·Π°ΠΏΡ€Π΅Ρ‰Π΅Π½Ρ‹ Π² Π·Π°ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ вСрсии ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. Π₯ΠΎΠ°Ρ€[123], ΠΎΠ΄Π½Π°ΠΊΠΎ, сдСлал Ρ‚Π°ΠΊΠΎΠ΅ Π·Π°ΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅:

Β«Π’ ΠΊΠΎΠ½Ρ†Π΅ ΠΊΠΎΠ½Ρ†ΠΎΠ², абсурдно Π΄Π΅Π»Π°Ρ‚ΡŒ Ρ‚Ρ‰Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ бСзопасности ΠΏΡ€ΠΈ ΠΎΡ‚Π»Π°Π΄ΠΎΡ‡Π½Ρ‹Ρ… запусках, ΠΊΠΎΠ³Π΄Π° ΠΊ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°ΠΌ Π½Π΅Ρ‚ Π½ΠΈΠΊΠ°ΠΊΠΎΠ³ΠΎ довСрия, Π° Π·Π°Ρ‚Π΅ΠΌ ΡƒΠ΄Π°Π»ΡΡ‚ΡŒ ΠΈΡ… ΠΈΠ· Ρ„ΠΈΠ½Π°Π»ΡŒΠ½Ρ‹Ρ… вСрсий, ΠΊΠΎΠ³Π΄Π° ΠΎΡˆΠΈΠ±ΠΎΡ‡Π½Ρ‹ΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π΄ΠΎΡ€ΠΎΠ³ΠΈΠΌ ΠΈΠ»ΠΈ катастрофичСским. Π§Ρ‚ΠΎ Π±Ρ‹ ΠΌΡ‹ ΠΏΠΎΠ΄ΡƒΠΌΠ°Π»ΠΈ ΠΎΠ± энтузиастС-ΠΌΠΎΡ€Π΅ΠΏΠ»Π°Π²Π°Ρ‚Π΅Π»Π΅, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π½Π°Π΄Π΅Π²Π°Π΅Ρ‚ свой ΡΠΏΠ°ΡΠ°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΆΠΈΠ»Π΅Ρ‚ ΠΏΡ€ΠΈ Ρ‚Ρ€Π΅Π½ΠΈΡ€ΠΎΠ²ΠΊΠ΅ Π½Π° сухой Π·Π΅ΠΌΠ»Π΅ ΠΈ снимаСт Π΅Π³ΠΎ, ΠΊΠ°ΠΊ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π²Ρ‹Ρ…ΠΎΠ΄ΠΈΡ‚ Π² ΠΌΠΎΡ€Π΅?Β»

Π‘ Ρ‚Π°ΠΊΠΈΠΌΠΈ мнСниями, наша рСкомСндация Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π²ΠΎ Π²Π½ΠΈΠΌΠ°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠΌ использовании ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠ² ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ- Π²ΠΎ-ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, для любого Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ рассмотритС Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ использования вмСсто Π½Π΅Π³ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ исполнСния. Π’ΠΎ-Π²Ρ‚ΠΎΡ€Ρ‹Ρ…, Ρ‚Ρ‰Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ размСститС свой ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ Π±Ρ‹Π»ΠΎ Π²ΠΎΠ·Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ ΠΏΡ€ΠΎΡ‚ΠΈΠ² ΠΈΡ… оставлСния Π½Π° своСм мСстС Π»Π°ΠΆΠ΅ Π² Ρ„ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠΉ вСрсии вашСй ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹.

НаконСц, ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΠΌ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅ ΠΈΠ· Ρ€Π°Π·Π΄Π΅Π»Π° «Ошибки» справочной страницы GNU/Linux assert(3):

assert() Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ ΠΊΠ°ΠΊ макрос: Ссли Ρƒ провСряСмого выраТСния Π΅ΡΡ‚ΡŒ ΠΏΠΎΠ±ΠΎΡ‡Π½Ρ‹Π΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹, ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΌΠ΅Π½ΡΡ‚ΡŒΡΡ Π² зависимости ΠΎΡ‚ Ρ‚ΠΎΠ³ΠΎ, ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ Π»ΠΈ NDEBUG. Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ гСйзСнбСрговскиС ошибки, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΡΡ‡Π΅Π·Π°ΡŽΡ‚ ΠΏΡ€ΠΈ ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΈ Ρ€Π΅ΠΆΠΈΠΌΠ° ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ.

Π—Π½Π°ΠΌΠ΅Π½ΠΈΡ‚Ρ‹ΠΉ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏ нСопрСдСлСнности Π“Π΅ΠΉΠ·Π΅Π½Π±Π΅Ρ€Π³Π° ΠΈΠ· Ρ„ΠΈΠ·ΠΈΠΊΠΈ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Ρ‡Π΅ΠΌ Π±ΠΎΠ»Π΅Π΅ Ρ‚ΠΎΡ‡Π½ΠΎ Π²Ρ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚Π΅ ΡΠΊΠΎΡ€ΠΎΡΡ‚ΡŒ частицы, Ρ‚Π΅ΠΌ ΠΌΠ΅Π½Π΅Π΅ Ρ‚ΠΎΡ‡Π½ΠΎ Π²Ρ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚Π΅ Π΅Π΅ ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, ΠΈ Π½Π°ΠΎΠ±ΠΎΡ€ΠΎΡ‚. Π’ Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°Ρ… нСпрофСссионала это ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ Ρ‡Ρ‚ΠΎ простой Ρ„Π°ΠΊΡ‚ наблюдСния частицы влияСт Π½Π° Π½Π΅Π΅.

Π‘Ρ…ΠΎΠ΄Π½ΠΎΠ΅ явлСниС ΡΠΎΠ²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ Π² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ, Π½Π΅ связанном с Ρ„ΠΈΠ·ΠΈΠΊΠΎΠΉ частиц: дСйствиС компилирования ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ для ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ ΠΈΠ»ΠΈ запуска Π΅Π΅ Π° Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. Π’ частности, ΠΏΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½Π°Ρ ошибка ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΡ‡Π΅Π·Π½ΡƒΡ‚ΡŒ. Π’Π°ΠΊΠΈΠ΅ ошибки Π² Ρ€Π°Π·Π³ΠΎΠ²ΠΎΡ€Π΅ Π½Π°Π·Ρ‹Π²Π°ΡŽΡ‚ гСйзСнбСрговскими.

Бправочная страница прСдостСрСгаСт нас ΠΎΡ‚ использования ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π°Ρ… assert() Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ с ΠΏΠΎΠ±ΠΎΡ‡Π½Ρ‹ΠΌΠΈ эффСктами:

assert(*p++ == '\n');

Π—Π΄Π΅ΡΡŒ ΠΏΠΎΠ±ΠΎΡ‡Π½Ρ‹ΠΌ эффСктом являСтся ΡƒΠ²Π΅Π»ΠΈΡ‡Π΅Π½ΠΈΠ΅ указатСля p ΠΊΠ°ΠΊ Ρ‡Π°ΡΡ‚ΡŒ тСста. Когда ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ NDEBUG, Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ выраТСния исчСзаСт ΠΈΠ· исходного ΠΊΠΎΠ΄Π°; ΠΎΠ½ Π½ΠΈΠΊΠΎΠ³Π΄Π° Π½Π΅ исполняСтся. Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ Π½Π΅ΠΎΠΆΠΈΠ΄Π°Π½Π½ΠΎΠΉ Π½Π΅ΡƒΠ΄Π°Ρ‡Π΅. Однако, ΠΊΠ°ΠΊ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈ ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΊΠ΅ ΠΊ ΠΎΡ‚Π»Π°Π΄ΠΊΠ΅ Π·Π°ΠΏΡ€Π΅Ρ‚ Π½Π° ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ отмСняСтся, всС Π½Π°Ρ‡ΠΈΠ½Π°Π΅Ρ‚ снова Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ! Π’Π°ΠΊΠΈΠ΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ Ρ‚Ρ€ΡƒΠ΄Π½ΠΎ ΠΎΡ‚ΡΠ»Π΅Π΄ΠΈΡ‚ΡŒ.

12.2. НизкоуровнСвая ΠΏΠ°ΠΌΡΡ‚ΡŒ: Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ memXXX()

НСсколько Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½Ρ‹ΠΌΠΈ Π±Π»ΠΎΠΊΠ°ΠΌΠΈ памяти Π½ΠΈΠ·ΠΊΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²Ρ‹Π΅ слуТбы. ВсС ΠΈΡ… ΠΈΠΌΠ΅Π½Π° Π½Π°Ρ‡ΠΈΠ½Π°ΡŽΡ‚ΡΡ с прСфикса 'mem':

#include <string.h> /* ISO C */


void *memset(void *buf, int val, size_t count);

void *memcpy(void *dest, const void *src, size_t count);

void *memmove(void *dest, const void *src, size_t count);

void *memccpy(void *dest, const void *src, int val, size_t count);

int memcmp(const void *buf1, const void *buf2, size_t count);

void *memchr(const void *buf, int val, size_t count);

12.2.1. Π—Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ памяти: memset()

Ѐункция memset() ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ val (ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠ΅ ΠΊΠ°ΠΊ unsigned char) Π² ΠΏΠ΅Ρ€Π²Ρ‹Π΅ count Π±Π°ΠΉΡ‚ΠΎΠ² Π±ΡƒΡ„Π΅Ρ€Π° buf. Она особСнно ΠΏΠΎΠ»Π΅Π·Π½Π° для обнулСния Π±Π»ΠΎΠΊΠΎΠ² динамичСской памяти:

void *p = malloc(count);

if (p != NULL)

 memset(p, 0, count);

Однако memset() ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ с любой Ρ€Π°Π·Π½ΠΎΠ²ΠΈΠ΄Π½ΠΎΡΡ‚ΡŒΡŽ памяти, Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ с динамичСской. Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ являСтся ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚: buf.

12.2.2. ΠšΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ памяти: memcpy(), memmove() ΠΈ memccpy()

Π’Ρ€ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΊΠΎΠΏΠΈΡ€ΡƒΡŽΡ‚ ΠΎΠ΄ΠΈΠ½ Π±Π»ΠΎΠΊ памяти Π² Π΄Ρ€ΡƒΠ³ΠΎΠΉ. ΠŸΠ΅Ρ€Π²Ρ‹Π΅ Π΄Π²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΎΡ‚Π»ΠΈΡ‡Π°ΡŽΡ‚ΡΡ Π² ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ΠΏΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰ΠΈΡ…ΡΡ областСй памяти; Ρ‚Ρ€Π΅Ρ‚ΡŒΡ ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ ΠΏΠ°ΠΌΡΡ‚ΡŒ, Π½ΠΎ останавливаСтся ΠΏΡ€ΠΈ встрСчС с ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ.

void *memcpy(void *dest, const void *src, size_t count)

Π­Ρ‚ΠΎ ΠΏΡ€ΠΎΡΡ‚Π΅ΠΉΡˆΠ°Ρ функция. Она ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ count Π±Π°ΠΉΡ‚ΠΎΠ² ΠΈΠ· src Π² dest. Она Π½Π΅ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰ΠΈΠ΅ΡΡ области памяти. Ѐункция Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ dest.

void *memmove(void *dest, const void *src, size_t count)

Подобно memcpy(), ΠΎΠ½Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ count Π±Π°ΠΉΡ‚ΠΎΠ² ΠΈΠ· src Π² dest. Однако, ΠΎΠ½Π° ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ ΠΏΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰ΠΈΠ΅ΡΡ области памяти. Ѐункция Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ dest.

void *memccpy(void *dest, const void *src, int val, size_t count)

Π­Ρ‚Π° ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ Π±Π°ΠΉΡ‚Ρ‹ ΠΈΠ· src Π² dest, ΠΎΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°ΡΡΡŒ Π»ΠΈΠ±ΠΎ послС копирования val Π² dest, Π»ΠΈΠ±ΠΎ послС копирования count Π±Π°ΠΉΡ‚ΠΎΠ². Если ΠΎΠ½Π° Π½Π°Ρ…ΠΎΠ΄ΠΈΡ‚ val, Ρ‚ΠΎ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π² dest сразу Π·Π° val. Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС возвращаСтся NULL.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ, Π² Ρ‡Π΅ΠΌ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° с ΠΏΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΉΡΡ ΠΏΠ°ΠΌΡΡ‚ΡŒΡŽ? Рассмотрим рис. 12.1.

Рис. 12.1. ΠŸΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰ΠΈΠ΅ΡΡ ΠΊΠΎΠΏΠΈΠΈ

ЦСлью являСтся ΡΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅ экзСмпляра struct xyz ΠΎΡ‚ data[0] Π΄ΠΎ data[3] Π² участок ΠΎΡ‚ data[3] Π΄ΠΎ data[6]. Π—Π΄Π΅ΡΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉ являСтся data[3], ΠΏΠΎΠ±Π°ΠΉΡ‚ΠΎΠ²ΠΎΠ΅ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ с ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠ΅ΠΌ Π² памяти ΠΈΠ· data[0] Π·Π°Ρ‚Ρ€Π΅Ρ‚ data[3] Π΄ΠΎ Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΎΠ½ Π±ΡƒΠ΄Π΅Ρ‚ бСзопасно скопирован Π² data[6]! (ΠœΠΎΠΆΠ΅Ρ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ Ρ‚Π°ΠΊΠΆΠ΅ сцСнарий, ΠΊΠΎΠ³Π΄Π° ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ Π² памяти Π² ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠΌ Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠΈ Ρ€Π°Π·Ρ€ΡƒΡˆΠΈΡ‚ ΠΏΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰ΠΈΠ΅ΡΡ Π΄Π°Π½Π½Ρ‹Π΅.)

Ѐункция memcpy() Π±Ρ‹Π»Π° ΠΏΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ Π² System V API для копирования Π±Π»ΠΎΠΊΠΎΠ² памяти; Π΅Π΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ для ΠΏΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰ΠΈΡ…ΡΡ Π±Π»ΠΎΠΊΠΎΠ² памяти Π½Π΅ Π±Ρ‹Π»Π° ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π° Ρ‚Π΅ΠΌ ΠΈΠ»ΠΈ ΠΈΠ½Ρ‹ΠΌ способом. Для стандарта Π‘ 1989 Π³. ΠΊΠΎΠΌΠΈΡ‚Π΅Ρ‚ почувствовал, Ρ‡Ρ‚ΠΎ это отсутствиС опрСдСлСнности являСтся ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΎΠΉ, поэтому ΠΎΠ½ΠΈ ΠΏΡ€ΠΈΠ΄ΡƒΠΌΠ°Π»ΠΈ memmove(). Для ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠΉ совмСстимости memcpy() Π±Ρ‹Π»Π° оставлСна, ΠΏΡ€ΠΈΡ‡Π΅ΠΌ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ для ΠΏΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰Π΅ΠΉΡΡ памяти Π±Ρ‹Π»ΠΎ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎ ΠΎΡ‚ΠΌΠ΅Ρ‡Π΅Π½ΠΎ ΠΊΠ°ΠΊ Π½Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ΅, Π° Π² качСствС ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹, ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ Ρ€Π°Π·Ρ€Π΅ΡˆΠ°ΡŽΡ‰Π΅ΠΉ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ½Ρ‹Π΅ случаи, Π±Ρ‹Π»Π° ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½Π° memmove().

ΠšΠ°ΠΊΡƒΡŽ ΠΈΠ· Π½ΠΈΡ… ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² своСм ΠΊΠΎΠ΄Π΅? Для Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅Ρ‡Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, которая Π½Π΅ Π·Π½Π°Π΅Ρ‚, ΠΊΠ°ΠΊΠΈΠ΅ области памяти Π΅ΠΉ ΠΏΠ΅Ρ€Π΅Π΄Π°ΡŽΡ‚ΡΡ, слСдуСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ memmove(). Π’Π°ΠΊΠΈΠΌ способом Π²Ρ‹ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚Π΅, Ρ‡Ρ‚ΠΎ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ с ΠΏΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΌΠΈΡΡ областями. Для ΠΊΠΎΠ΄Π° прилоТСния, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Β«Π·Π½Π°Π΅Ρ‚Β», Ρ‡Ρ‚ΠΎ Π΄Π²Π΅ области Π½Π΅ ΠΏΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Π²Π°ΡŽΡ‚ΡΡ, ΠΌΠΎΠΆΠ½ΠΎ бСзопасно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ memcpy().

Как для memcpy(), Ρ‚Π°ΠΊ ΠΈ для memmove() (ΠΊΠ°ΠΊ ΠΈ для strcpy()) Π±ΡƒΡ„Π΅Ρ€ назначСния являСтся ΠΏΠ΅Ρ€Π²Ρ‹ΠΌ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠΌ, Π° источник β€” Π²Ρ‚ΠΎΡ€Ρ‹ΠΌ. Π§Ρ‚ΠΎΠ±Ρ‹ Π·Π°ΠΏΠΎΠΌΠ½ΠΈΡ‚ΡŒ это, ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° порядок, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ‚ΠΎΡ‚ ΠΆΠ΅ самый, ΠΊΠ°ΠΊ Π² ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π΅ присваивания:

dest = src;

(Π‘ΠΏΡ€Π°Π²ΠΎΡ‡Π½Ρ‹Π΅ страницы Π²ΠΎ ΠΌΠ½ΠΎΠ³ΠΈΡ… систСмах Π½Π΅ ΠΏΠΎΠΌΠΎΠ³Π°ΡŽΡ‚, прСдлагая ΠΏΡ€ΠΎΡ‚ΠΎΡ‚ΠΈΠΏ Π² Π²ΠΈΠ΄Π΅ 'void *memcpy(void *buf1, void *buf2, size_t n)' ΠΈ полагаясь Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ тСкст ΠΎΠ±ΡŠΡΡΠ½ΠΈΡ‚, Ρ‡Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Ρ‡Ρ‚ΠΎ. К ΡΡ‡Π°ΡΡ‚ΡŒΡŽ, справочная страница GNU/Linux ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Π±ΠΎΠ»Π΅Π΅ осмыслСнныС ΠΈΠΌΠ΅Π½Π°.)

12.2.3. Π‘Ρ€Π°Π²Π½Π΅Π½ΠΈΠ΅ Π±Π»ΠΎΠΊΠΎΠ² памяти: memcmp()

Ѐункция memcmp() сравниваСт count Π±Π°ΠΉΡ‚ΠΎΠ² ΠΈΠ· Π΄Π²ΡƒΡ… ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½Ρ‹Ρ… Π±ΡƒΡ„Π΅Ρ€ΠΎΠ² Π΄Π°Π½Π½Ρ‹Ρ…. Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ΅ Сю Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ strcmp(): ΠΎΡ‚Ρ€ΠΈΡ†Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠ΅, Π½ΡƒΠ»Π΅Π²ΠΎΠ΅ ΠΈΠ»ΠΈ ΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ΅, Ссли ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Π±ΡƒΡ„Π΅Ρ€ мСньшС, Ρ€Π°Π²Π΅Π½ ΠΈΠ»ΠΈ большС Π²Ρ‚ΠΎΡ€ΠΎΠ³ΠΎ.

Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΠΎΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΠΎΠ²Π°Ρ‚ΡŒΡΡ: Β«ΠŸΠΎΡ‡Π΅ΠΌΡƒ Π±Ρ‹ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ для Ρ‚Π°ΠΊΠΎΠ³ΠΎ сравнСния strcmp()?Β» Π Π°Π·Π½ΠΈΡ†Π° ΠΌΠ΅ΠΆΠ΄Ρƒ двумя функциями Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ memcmp() Π½Π΅ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π²ΠΎ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½ΡƒΠ»Π΅Π²Ρ‹Π΅ Π±Π°ΠΉΡ‚Ρ‹ (Π·Π°Π²Π΅Ρ€ΡˆΠ°ΡŽΡ‰ΠΈΠΉ строку '\0'.) Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, memcmp() являСтся Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ, которая ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ, ΠΊΠΎΠ³Π΄Π° Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΡΡ€Π°Π²Π½ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½Ρ‹Π΅ Π΄Π²ΠΎΠΈΡ‡Π½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅.

Π”Ρ€ΡƒΠ³ΠΈΠΌ прСимущСством memcmp() являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ ΠΎΠ½Π° быстрСС Ρ‚ΠΈΠΏΠΈΡ‡Π½ΠΎΠΉ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π½Π° C:

/* 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;

}

Π‘ΠΊΠΎΡ€ΠΎΡΡ‚ΡŒ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ достигнута Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ использования ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Ρ… инструкций Β«Π±Π»ΠΎΡ‡Π½ΠΎΠ³ΠΎ сравнСния памяти», ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°ΡŽΡ‚ ΠΌΠ½ΠΎΠ³ΠΈΠ΅ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹, ΠΈΠ»ΠΈ Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ сравнСния Π΅Π΄ΠΈΠ½ΠΈΡ†, ΠΏΡ€Π΅Π²Ρ‹ΡˆΠ°ΡŽΡ‰ΠΈΡ… Π±Π°ΠΉΡ‚Ρ‹. (Π­Ρ‚Π° послСдняя опСрация ΠΊΠΎΠ²Π°Ρ€Π½Π°, ΠΈ Π»ΡƒΡ‡ΡˆΠ΅ ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π΅Π΅ Π°Π²Ρ‚ΠΎΡ€Ρƒ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ.)