C - зачем нужен strcpy()
Может кто-нибудь объяснить мне, почему strcpy() необходимо для назначения строк массивам символов, например, в следующем фрагменте кода.
int main(void) {
char s[4];
s = "abc"; //Fails
strcpy(s, "abc"); //Succeeds
return 0;
}
В чем причина неудачи s = "abc"
? И почему strcpy() единственный способ назначить строки массивам char после их объявления? Мне кажется странным, что вам нужно использовать функцию для выполнения основного задания.
Ответы
Ответ 1
Массивы в C не являются назначаемыми и не копируемыми. Это как раз то, как массивы находятся в C. Исторически, в контексте стоимости (по RHS присвоения) массивы распадаются на указатели, что формально предотвращает назначение и копирование. Это относится ко всем массивам не только к массивам char
.
Язык C наследует поведение этих массивов от его предшественников - языков B и BCPL. В этих языках массивы были представлены физическими указателями. (И, очевидно, повторное назначение указателей - это не то, что вы хотели бы сделать, когда вы назначаете один массив другому.) В языках C массивы не являются указателями, но они "имитируют" историческое поведение массивов B и BCPL путем разложения для указателей в большинстве случаев. Это историческое наследие - это то, что сохраняет C массивы, не подлежащие копированию, по сей день.
Одним из исключений из вышеизложенного является инициализация строковым литералом. То есть вы можете сделать
char c[] = "abc";
но что он.
Это означает, что всякий раз, когда вы хотите скопировать массив, вы должны использовать функцию копирования памяти на уровне библиотеки, например memcpy
. strcpy
- это просто аромат, специально предназначенный для работы со строками.
Ответ 2
Это просто, какие массивы находятся в C. Вы не можете назначить их. Вы можете использовать указатели, если хотите:
char *p;
p = "abc";
Кстати, есть C FAQ.
Массивы являются "гражданами второго сорта" в C; один итог этого предвзятость заключается в том, что вы не можете назначить им.
Ответ 3
Короткий ответ: исторические причины. C никогда не имел встроенного строкового типа. Только после того, как С++ появился, появился std::string, и даже это не пришло с первой версией
Длинный ответ: тип "abc" не char[]
, а скорее char *
. strcpy
- это один из механизмов, с помощью которого вы можете скопировать данные, на которые указывает указатель (в данном случае это ABC).
strcpy
не единственный способ инициализации массива, однако он достаточно умен, чтобы обнаруживать и уважать завершение 0 в конце строки. Вы также можете использовать memcpy
для копирования строки в s
, но для этого требуется передать длину данных, которые нужно скопировать, и обеспечить завершение 0 (NULL) в s
Ответ 4
На языке C отсутствует удобный синтаксис для получения указателя на строковый литерал вместе с указанием его длины. Некоторые языки, включая много диалектов Паскаля, префикс каждой строки с байтом, сообщающим о своей длине; это хорошо работает для многих целей, но ограничивает строковые литералы до 255 символов. C позволяет использовать строковые литералы любой длины, но добавляет только один байт служебных данных независимо от длины.
Строки с нулевым завершением уступают другим формам почти для всех целей, отличных от строковых литералов, но литералы настолько далеко отстоят от самой распространенной формы строки, с которой приходится сталкиваться многим программам, и, следовательно, существует значительное преимущество наличие библиотечных функций с ними эффективно; тогда становится проще использовать строки с нулевым завершением в случаях, когда они менее идеальны, чем иметь отдельный набор библиотечных подпрограмм для других типов.