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 позволяет использовать строковые литералы любой длины, но добавляет только один байт служебной информации независимо от длины.

Строки с нулевым символом в конце уступают другим формам практически для любой цели, кроме строковых литералов, но литералы являются наиболее распространенной формой строк, с которой приходится сталкиваться многим программам, и, таким образом, наличие библиотечных функций дает значительное преимущество. эффективно справляться с ними; тогда становится проще использовать строки с нулевым символом в конце, когда они не идеальны, чем иметь отдельный набор библиотечных подпрограмм для других типов.

Другие вопросы по тегам