c основы работы со строками, почему неназначенные?

Я пытаюсь изучить основы, я думаю, что объявление char [] и присвоение ему строки сработает. Благодарность

int size = 100;
char str[size];

str = "\x80\xbb\x00\xcd";

выдает ошибку "несовместимые типы в присвоении". что случилось? Благодарность


person alfo    schedule 26.09.2010    source источник
comment
Прочтите это: stackoverflow.com/questions/2124935/c-strings- путаница /   -  person t0mm13b    schedule 27.09.2010
comment
Массивы не являются указателями ... и указатели не являются массивами ... прочтите это: c-faq. ru / aryptr / index.html   -  person pmg    schedule 27.09.2010


Ответы (6)


Вы можете использовать строковый литерал для инициализации массива char, но вы не можете назначить массив char (как и любой другой массив). OTOH, вы можете назначить указатель, поэтому будет разрешено следующее:

char *str;

str = "\x80\xbb\x00\xcd";
person Jerry Coffin    schedule 26.09.2010
comment
хм. спасибо за помощь. для меня это странно, что я могу объявить str [size], а затем использовать что-то вроде fgets (3) для записи в эту память или strcpy (str2, str) для записи в нее, но не могу установить здесь str = string ; это почему? - person alfo; 27.09.2010
comment
Я бы использовал const char* при работе со строковыми литералами. - person Matthew; 27.09.2010
comment
@alfo: просто C не позволяет вам изменять массив, назначая ему содержимое другого массива с помощью =. На самом деле нет серьезной причины почему - просто язык требует, чтобы вы использовали другой механизм (memcpy() в целом) для этого. - person caf; 27.09.2010

На самом деле это одна из самых сложных частей изучения языка программирования .... str - это массив, то есть часть памяти (размер, умноженная на символ, поэтому размер символов), которая была зарезервирована и помечена как str. str [0] - это первый символ, str [1] - второй ... str [size-1] - последний. str сама по себе, без указания какого-либо символа, является указателем на зону памяти, которая была создана, когда вы сделали

char str[size]

Как ясно сказал Джерри, в C вы не можете инициализировать массивы таким образом. Вам нужно скопировать из одного массива в другой, поэтому вы можете сделать что-то вроде этого

strncpy(str, "\x80\xbb\x00\xcd", size); /* Copy up to size characters */
str[size-1]='\0'; /* Make sure that the string is null terminated for small values of size */

Подводя итог: очень важно различать указатели, области памяти и массив.

Удачи - я почти уверен, что за меньшее время, чем вы думаете, вы освоите эти концепции :)

person Javier    schedule 26.09.2010
comment
нет str не является указателем. Сделайте sizeof str, чтобы увидеть разницу. Самый простой способ увидеть, что str "незаметно" преобразуется в указатель на "правой стороне" выражений, но не слева от оператора присваивания. - person Jens Gustedt; 27.09.2010
comment
Да, Йенс, ты прав, я поправляюсь. Большое спасибо, что указали на это :) - person Javier; 27.09.2010
comment
Также вы неправильно используете слово инициализировать в начале абзаца, как ясно сказал Джерри. - person R.. GitHub STOP HELPING ICE; 27.09.2010
comment
Приношу свои извинения, английский не мой основной язык. - person Javier; 27.09.2010

Char-array может быть неявно преобразован в char * при использовании как Rvalue, но не при использовании как Lvalue - вот почему присвоение не сработает.

person Robert    schedule 26.09.2010

Вы не можете назначить массив contents с помощью =operator. Это просто факт дизайна языка C. Вы можете инициализировать массив в объявлении, например

char str[size] = "\x80\xbb\x00\xcd";

но эта операция отличается от задания. Обратите внимание, что в этом случае в конец строки будет добавлен дополнительный '\ 0'.

Предупреждение о «несовместимых типах» возникает из-за того, как язык обрабатывает выражения массива. Прежде всего, строковые литералы хранятся в виде массивов char со статическим размером (то есть они существуют в течение всего времени существования программы). Таким образом, тип строкового литерала "\ x80 \ xbb \ x00 \ xcd" - "4 5-элементный массив char". Однако в большинстве случаев выражение типа массива будет неявно преобразовано («распадаться») из типа «N-элементный массив T» в «указатель на T», и значением выражения будет адрес первого элемент в массиве. Итак, когда вы написали заявление

str = "\x80\xbb\x00\xcd";

тип литерала был неявно преобразован из "4 5-элементного массива char" в "указатель на char", но целью присвоения является тип "100-элементный массив char", и типы несовместимы (помимо того, что выражение массива не может быть целью оператора =).

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

Изменить на комментарий R ниже, я вычеркнул самые глупые разделы своего ответа.

person John Bode    schedule 26.09.2010
comment
Строковый литерал "\x80\xbb\x00\xcd" уже содержит завершающий 0, поэтому неправильно говорить о добавлении последнего 0 при использовании его в качестве инициализатора. Кроме того, частично инициализированный объект в C всегда имеет оставшуюся часть объекта, заполненную нулями. Это не относится к строкам. - person R.. GitHub STOP HELPING ICE; 27.09.2010

Чтобы назначить строковый литерал массиву str, вы можете использовать функцию копирования строки strcpy.

person Christian Ammer    schedule 26.09.2010
comment
Чтобы быть более точным: вы копируете символы (строку 'content'), а не присваиваете значение. - person Robert; 27.09.2010
comment
Да назначать не правильно. Я хотел указать на возможность установки массива str. - person Christian Ammer; 27.09.2010

str - это имя массива. Имя массива - это адрес 0-го элемента. Следовательно, str является константой указателя. Вы не можете изменить значение константы указателя, так же как вы не можете изменить константу (например, вы не можете сделать 6 = 5).

person Kizaru    schedule 26.09.2010
comment
Да, str - это массив символов. Но само имя str, когда оно используется в этом контексте, является константой указателя. Возможно, я использовал другую терминологию, но что еще вы бы назвали str в этом контексте, str = \ x80 \ xbb \ x00 \ xcd; - person Kizaru; 27.09.2010
comment
Имя массива - это адрес 0-го элемента. Следовательно, str является константой указателя. Вы, похоже, не согласны с этим заявлением, поэтому я уточню. Я называю адрес константой указателя. Например, предположим, что у вас есть int x; int * y; у = & х; Здесь & x [то, что мы с коллегами называем] константой указателя - это значение, которое является адресом некоторого другого места в памяти, и его нельзя изменить. Это не указатель. Помимо этого, какие проблемы с моим сообщением? - person Kizaru; 27.09.2010
comment
Проблема в том, что выражение str не всегда рассматривается как указатель. Вот соответствующий параграф (раздел 6.3.2.1, параграф 3) За исключением случаев, когда это операнд оператора sizeof или унарного оператора &, или строковый литерал, используемый для инициализации массива, выражение, которое имеет тип '' массив типа '' преобразуется в выражение с типом '' указатель на тип '', которое указывает на начальный элемент объекта массива и не является lvalue. Если объект массива имеет класс хранения регистров, поведение не определено. Акцент мой. - person John Bode; 27.09.2010
comment
Кроме того, то, что вы называете константами указателя, более широко известно как rvalues ​​(то есть значение выражения). - person dreamlax; 27.09.2010