C - зачем нужна strcpy () - PullRequest
       17

C - зачем нужна strcpy ()

26 голосов
/ 01 августа 2011

Может кто-нибудь объяснить мне, почему strcpy () необходим для назначения строк массивам символов, например, в следующем фрагменте кода.

int main(void) {

char s[4];

s = "abc"; //Fails
strcpy(s, "abc"); //Succeeds

return 0;
}

В чем причина сбоя s = "abc"?И почему strcpy () является единственным способом присвоения строк массивам символов после их объявления?Мне кажется странным, что вы должны использовать функцию для выполнения базового задания.

Ответы [ 4 ]

29 голосов
/ 01 августа 2011

Массивы в C не могут быть назначены и инициализированы без копирования. Именно так обстоит дело с массивами в C. Исторически в контексте значений (в RHS назначения) массивы распадаются на указатели, что формально предотвращает назначение и инициализацию копирования. Это относится ко всем массивам, а не только к char массивам.

Язык C наследует это поведение массивов от своих предшественников - языков B и BCPL. На этих языках массивы были представлены физическими указателями. (И, очевидно, переназначение указателей - это не то, что вы хотели бы произойти, когда вы присваиваете один массив другому.) В языке C массивы не являются указателями, однако они «имитируют» историческое поведение массивов B и BCPL, разрушаясь указатели в большинстве случаев. Благодаря этому историческому наследию массивы C не подлежат копированию до сих пор.

Единственным исключением из вышеприведенного является инициализация строковым литералом. То есть Вы можете сделать

char c[] = "abc";

но это все.

Это означает, что всякий раз, когда вы хотите скопировать массив, вы должны использовать функцию копирования памяти на уровне библиотеки, например memcpy. strcpy - это просто разновидность, специально предназначенная для работы со строками.

13 голосов
/ 01 августа 2011

Это просто то, что массивы в C. Вы не можете назначить им. Вы можете использовать указатели, если вам нравится:

char *p;
p = "abc";

Кстати, есть C FAQ .

Массивы являются "гражданами второго сорта" в C; один результат этого предубеждением является то, что вы не можете присвоить им .

1 голос
/ 01 августа 2011

Краткий ответ: исторические причины. C никогда не имел встроенного строкового типа. Только когда появился C ++, появилась std :: string, и даже она не появилась с первыми реализациями

Длинный ответ: тип "abc" не char[], а скорее char *. strcpy - это один механизм, с помощью которого вы можете копировать данные, на которые указывает указатель (в данном случае это ABC).

strcpy - не единственный способ инициализации массива, однако он достаточно умен, чтобы обнаружить и соблюдать завершающий 0 в конце строки. Вы также можете использовать memcpy, чтобы скопировать строку в s, но для этого необходимо указать длину копируемых данных и обеспечить наличие завершающего 0 (NULL) в s

0 голосов
/ 01 мая 2017

В языке C отсутствует какой-либо удобный синтаксис для получения указателя на строковый литерал и указания его длины. Некоторые языки, включая множество диалектов Паскаля, ставят перед каждой строкой байт, сообщающий о ее длине; это хорошо работает для многих целей, но ограничивает строковые литералы 255 символами. Подход C позволяет использовать строковые литералы любой длины, но добавляет только один байт служебной информации независимо от длины.

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

...