Подтвердить что ты не робот

Присвоение строк массивам символов

Я немного удивлен следующим.

Пример 1:

char s[100] = "abcd"; // declare and initialize - WORKS

Пример 2:

char s[100]; // declare
s = "hello"; // initalize - DOESN'T WORK ('lvalue required' error)

Мне интересно, почему второй подход не работает. Кажется естественным, что он должен (он работает с другими типами данных)? Может ли кто-нибудь объяснить мне логику этого?

4b9b3361

Ответ 1

При инициализации массива C позволяет вам заполнить его значениями. Так

char s[100] = "abcd";

в основном так же, как

int s[3] = { 1, 2, 3 };

но это не позволяет вам выполнять присваивание, так как s является массивом, а не свободным указателем. Значение

s = "abcd" 

это присвоить s значение указателя abcd но вы не можете изменить s так как ничто не будет указывать на массив.
Это может работать и работает, если s является char* - указателем, который может указывать на что угодно.

Если вы хотите скопировать строку, просто используйте strcpy.

Ответ 2

В Си нет такой вещи, как "строка". В Си строки - это одномерный массив char, заканчивающийся нулевым символом \0. Поскольку вы не можете назначать массивы в C, вы также не можете назначать строки. Литерал "привет" является синтаксическим сахаром для const char x[] = {'h','e','l','l','o','\0'};

Правильный путь будет:

char s[100];
strncpy(s, "hello", 100);

или еще лучше:

#define STRMAX 100
char    s[STRMAX];
size_t  len;
len = strncpy(s, "hello", STRMAX);

Ответ 3

Инициализация и назначение - это две различные операции, которые используют один и тот же оператор ( "=" ) здесь.

Ответ 4

1    char s[100];
2    s = "hello";

В приведенном примере s фактически инициализируется в строке 1, а не в строке 2. Даже если вы не присвоили ему значение явно в этот момент, компилятор сделал. На строке 2 вы выполняете операцию присваивания, и вы не можете назначить один массив символов другому массиву символов, подобных этому. Вам нужно будет использовать strcpy() или какой-то цикл для назначения каждого элемента массива.

Ответ 5

Чтобы расширить на ответ Sparr

Инициализация и назначение - это две различные операции, которые используют один и тот же оператор ( "=" ) здесь.

Подумайте об этом так:

Предположим, что есть 2 функции, называемые InitializeObject и AssignObject. Когда компилятор видит thing = value, он просматривает контекст и вызывает один InitializeObject, если вы создаете новый thing. Если вы этого не сделаете, вместо этого он называет AssignObject.

Обычно это нормально, поскольку InitializeObject и AssignObject обычно ведут себя одинаково. За исключением случаев использования массивов char (и нескольких других случаев краев), в этом случае они ведут себя по-разному. Зачем это делать? Хорошо, что целая другая статья связана с стеком против кучи и т.д. И т.д.

PS: В стороне, думая об этом таким образом, также поможет понять конструкторы копирования и другие подобные вещи, если вы когда-нибудь захотите в С++

Ответ 6

Обратите внимание, что вы все еще можете сделать:

s[0] = 'h';
s[1] = 'e';
s[2] = 'l';
s[3] = 'l';
s[4] = 'o';
s[5] = '\0';

Ответ 7

Я знаю, что на этот вопрос уже дан ответ, но я хотел бы поделиться ответом, который я дал кому-то, кто задал очень похожий вопрос в группе C/C++ в Facebook.


Массивы не имеют функций оператора присваивания *. Это означает, что вы не можете просто присвоить массив символов строковому литералу. Зачем? Потому что сам массив не имеет оператора присваивания. (* Это константный указатель, который нельзя изменить.)

массивы - это просто область смежной выделенной памяти, а имя массива фактически является указателем на первый элемент массива. (Цитата из https://www.quora.com/Can-we-copy-an-array-using-an-assignment-operator)

Чтобы скопировать строковый литерал (такой как "Hello world" или "abcd") в ваш массив char, вы должны вручную скопировать все элементы char строкового литерала в массив.

char s[100]; Это инициализирует пустой массив длиной 100.

Теперь, чтобы скопировать строковый литерал в этот массив, используйте strcpy

strcpy(s, "abcd"); Это скопирует содержимое строкового литерала "abcd" и скопирует его в массив s[100].

Вот отличный пример того, что он делает:

int i = 0; //start at 0
do {
    s[i] = ("Hello World")[i]; //assign s[i] to the string literal index i
} while(s[i++]); //continue the loop until the last char is null

Очевидно, вы должны использовать strcpy вместо этого пользовательского строкового литерального копира, но это хороший пример, который объясняет, как работает strcpy.

Надеюсь это поможет!

Ответ 8

Вы можете использовать это:

yylval.sval=strdup("VHDL + Volcal trance...");

Где yylval - char *. strdup от выполнения задания.

Ответ 9

Я бы использовал

char *s = "abcd";