Какая разница между strcpy и stpcpy?
При чтении справочной страницы strcpy
я обнаружил, что функция stpcpy
также существует. Однако единственная разница, которую я мог заметить на странице руководства:
char *
stpcpy(char *s1, const char *s2);
char *
strcpy(char *restrict s1, const char *restrict s2);
Итак, что означает restrict
здесь?
Ответы
Ответ 1
restrict
сообщает компилятору, что s1
и s2
указывают на разные массивы и что на массивах с заостренным доступом нет перекрытия. В некоторых случаях это может позволить компилятору выполнять дополнительные оптимизации (т.е. Возможно копировать блоки из нескольких символов без необходимости проверки на перекрытие).
Обратите также внимание, что возвращаемое значение отличается: stpcpy
возвращает указатель на \0
, который был скопирован в буфер назначения, в то время как strcpy
возвращает указатель на начало строки (эффективно это делает return s1;
).
Ответ 2
Вопрос, который вы задаете в заголовке и вопрос о restrict
, на самом деле являются двумя разными совершенно не связанными вопросами. Другие ответы уже предоставили вам хорошие ссылки, которые помогут вам узнать больше о restrict
.
Однако основное различие между этими двумя функционалами в действительности не является спецификатором restrict
. Фактически, в версии C99 версии языка C, 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
- нет.
Ответ 3
Запись в Wikipedia для restrict
Короче говоря, restrict
сообщает компилятору, что сегменты памяти, на которые указывают s1 и s2, не перекрываются; это позволяет коду выполнять меньшую проверку ошибок.
Ответ 4
Функция stpcpy()
копирует строку, на которую указывает src (включая завершающий символ '\0'
), в массив, на который указывает dest. Строки может не перекрываться, а целевая строка dest должна быть достаточно большой, чтобы получить копию.
Это удовлетворяет требованиям для restrict
, даже если это не в сигнатуре функции. Если C99 присутствует, он может быть добавлен.
stpcpy()
возвращает указатель на конец строки dest (то есть адрес конечного нулевого байта), а не на начало.
Это позволяет вам легче конкатенировать многие строки и более эффективно, так как src
можно "привязать" к указателю, возвращенному из последнего stpcpy()
. Наивная реализация альтернативы strcat
должна найти конец строки dest
до того, как она начнет копирование.
Обратите внимание на следующее:
Эта функция не является частью стандартов C или POSIX.1 и не является обычным в Unix-системах, но также не является изобретением GNU. Возможно, это происходит от MS-DOS. В настоящее время он также присутствует в BSD.
Ответ 5
Другое отличие - это возвращаемое значение. На странице man: "Функции strcpy() и strncpy() возвращают s1. Функция stpcpy() возвращает указатель на завершающий символ`\0 's1."
Ответ 6
strcpy возвращает s1, но stpcpy возвращает s1 + strlen (s2).