2009-02-23 4 views
44

Я немного удивлен следующим.Назначение строк массивам символов

Пример 1:

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

Пример 2:

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

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

ответ

38

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

char s[100] = "abcd"; 

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

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

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

s = "abcd" 

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

, если вы хотите скопировать строку просто использовать STRCPY

+3

Хороший ответ, за исключением того, что вы никогда не должны использовать простой strcpy. Используйте strncpy или strlcpy. – dwc

+3

Кроме того, s должен быть const char *, а не char *. – aib

+1

's [0] = 'x'; s [1] = 'y'; s [2] = 'z'; s [3] = 'm'; 'работает, если вы хотите заменить символы строки один за другим даже после инициализации. – RBT

9

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

41

В C. Строки являются массивами символов char, которые заканчиваются NULL по соглашению. Поскольку вы не можете назначать массивы на 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); 
+0

Не рекомендуется. Остерегайтесь странностей strncpy: http://stackoverflow.com/a/1258577/2974922 – nucleon

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

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

2

Для расширения Sparr's answer

Инициализация и назначение двух различных операций, которые происходят использовать один и тот же оператор («=») здесь.

Думай об этом, как это:

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

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

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

0

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

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

Это гораздо приятнее и проще в использовании strncpy(), хотя я уверен, что strncpy() делает именно это внутренне. –

+0

Конечно. Но это как можно ближе к «s =« привет »; Фактически, это должно было быть реализовано на C, видя, как вы можете назначить структуры. – aib

+0

Я имею в виду, что поэтапная копия по назначению в структурах, но не в массивах, не имеет смысла. – aib

-3

То, что я хотел бы использовать это

char *s = "abcd"; 
+0

Большинство из нас не будет, потому что это рискует неопределенным поведением. Вышеописанное безопасно только для 'const char *'. –

0

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

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

Где yylval - char *. strdup от этой работы.

+0

strdup от делает работу :) – Yekatandilburg