В чем разница между strcpy и stpcpy? - PullRequest
17 голосов
/ 29 апреля 2011

Читая справочную страницу для strcpy, я обнаружил, что функция stpcpy также существует.Тем не менее, единственное отличие, которое я мог заметить на странице руководства:

char *
stpcpy(char *s1, const char *s2);

char *
strcpy(char *restrict s1, const char *restrict s2);

Итак, что означает restrict здесь?

Ответы [ 6 ]

24 голосов
/ 29 апреля 2011

Вопрос, который вы задаете в названии, и вопрос о restrict - это на самом деле два совершенно не связанных между собой вопроса. Другие ответы уже дали вам хорошие ссылки, которые помогут вам узнать больше о restrict.

Однако, главное различие между этими двумя функциями не в спецификаторе restrict. На самом деле, в версии спецификации языка C99 для C99 strcpy также имеет квалификацию restrict по своим параметрам. То, что вы видите на своей справочной странице для strcpy, просто не обновляется, чтобы соответствовать C99.

Основным отличием (которое, похоже, вы пропустили) является возвращаемое значение stpcpy. stpcpy возвращает указатель на завершающий символ \0 целевой строки. Это сразу дает понять цель stpcpy и обоснование ее существования: эта функция предназначена для использования в качестве интеллектуальной замены функции strcat в ситуациях, когда вам нужно объединить несколько подстрок в одну строку. Видите ли, strcat работает довольно плохо в таком приложении (я бы даже сказал, что strcat не имеет смысла в реальном коде). Проблема с strcat заключается в том, что он повторно сканирует строку назначения каждый раз, когда вы добавляете в нее что-либо, тем самым выполняя много ненужной работы и в основном генерируя больше тепла, чем света. Например, следующий код страдает от этой проблемы

const char *part1, *part2, *part3, *part4;
...
char buffer[size]; /* assume that `size` is calculated properly */

strcpy(buffer, part1);
strcat(buffer, part2);
strcat(buffer, part3);
strcat(buffer, part4);

Этот код можно переопределить гораздо более разумным способом, используя stpcpy

stpcpy(stpcpy(stpcpy(stpcpy(buffer, part1), part2), part3), part4);

А если вам не нравятся цепочечные вызовы, вы можете использовать промежуточный указатель для хранения возвращаемого значения промежуточных stpcpy вызовов

char *end = buffer;

end = stpcpy(end, part1);
end = stpcpy(end, part2);
end = stpcpy(end, part3);
end = stpcpy(end, part4);

Конечно, стоит упомянуть, что strcpy и strcat являются стандартными функциями, а stpcpy - нет.

17 голосов
/ 29 апреля 2011

restrict сообщает компилятору, что s1 и s2 указывают на разные массивы и что в указанных массивах нет перекрытия.В некоторых случаях это может позволить компилятору выполнить дополнительную оптимизацию (т. Е. Он может скопировать блоки из нескольких символов без проверки на совпадение).

Обратите также внимание, что возвращаемое значение отличается: stpcpy возвращаетуказатель на \0, который был скопирован в буфер назначения, тогда как strcpy возвращает указатель на начало строки (фактически это return s1;).

6 голосов
/ 29 апреля 2011

Запись в Википедии для restrict

Вкратце, restrict сообщает компилятору, что сегменты памяти, на которые указывают s1 и s2, не перекрываются;это позволяет коду выполнять меньше проверки ошибок.

4 голосов
/ 29 апреля 2011

Функция stpcpy() копирует строку, на которую указывает src (включая завершающий символ '\0'), в массив, на который указывает dest. Струны может не перекрываться, и строка назначения dest должна быть достаточно большой, чтобы получить копию.

Это удовлетворяет требованиям для restrict, даже если его нет в сигнатуре функции. Если присутствует C99, его можно добавить.

stpcpy() возвращает указатель на конец строки dest (то есть адрес завершающего нулевого байта), а не на начало.

Это позволяет вам проще и эффективнее объединять многие строки, так как src может быть "привязан" к указателю, возвращенному из последнего stpcpy(). Наивная реализация альтернативы strcat должна найти конец строки dest, прежде чем она сможет начать копирование.

Обратите внимание на следующее:

Эта функция не является частью стандартов C или POSIX.1 и не является обычной для систем Unix, но также не является изобретением GNU. Возможно это приходит из MS-DOS. В настоящее время он также присутствует на BSD.

3 голосов
/ 29 сентября 2011

strcpy возвращает s1, но stpcpy возвращает s1 + strlen (s2).

3 голосов
/ 29 апреля 2011

Другая разница - возвращаемое значение.Со страницы man: «Функции strcpy () и strncpy () возвращают s1. Функция stpcpy () возвращает указатель на завершающий символ` \ 0 'в s1. "

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...