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