строковый литерал в c - PullRequest
       1

строковый литерал в c

7 голосов
/ 13 августа 2010

Почему следующий код недопустим?

typedef struct{
   char a[6];
} point;

int main()
{
   point p;
   p.a = "onetwo";
}

Это имеет какое-либо отношение к размеру литерала? или это просто недопустимо присваивать строковый литерал массиву char после его объявления?

Ответы [ 6 ]

12 голосов
/ 13 августа 2010

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

Когда вы делаете

char a[] = "something";

создает массив достаточного размера (включая завершающий ноль) и копирует строку в массив. Не рекомендуется указывать размер массива, когда вы инициализируете его строковым литералом - вы можете не учитывать нулевой символ.

Когда вы делаете

char a[10];
a = "something";

вы пытаетесь присвоить адрес массива, что недопустимо.

РЕДАКТИРОВАТЬ: как упоминалось в других ответах, вы можете сделать strcpy / strncpy, но убедитесь, что массив инициализирован с необходимой длиной.

strcpy(p.a, "12345");//give space for the \0
7 голосов
/ 13 августа 2010

Массивы non modifiable lvalues. Таким образом, вы не можете назначить им. Левая сторона оператора присваивания должна быть modifiable lvalue.

Однако вы можете инициализировать массив, когда он определен.

Например:

 char a[] = "Hello World" ;// this is legal
 char a[]={'H','e','l','l','o',' ','W','o','r','l','d','\0'};//this is also legal

 //but

 char a[20];
 a = "Hello World" ;// is illegal 

Однако вы можете использовать strncpy(a, "Hello World",20);

7 голосов
/ 13 августа 2010

Вы никогда не можете назначить массивы после того, как они были созданы;это в равной степени незаконно:

int foo[4];
int bar[4];
foo = bar;

Вам необходимо использовать указатели или назначить индекс массива;это допустимо:

p.a[0] = 'o';

Если вы хотите оставить массив в структуре, вы можете использовать такую ​​функцию, как strcpy:

strncpy(p.a, "onetwo", 6);

(обратите внимание, чтомассив char должен быть достаточно большим, чтобы также содержать nul-терминатор, так что вы, вероятно, захотите сделать его char a[7] и изменить последний аргумент на strncpy на 7)

3 голосов
/ 13 августа 2010

Как уже отмечалось в других ответах, вы можете инициализировать массив символов только строковым литералом, вы не можете присвоить строковый литерал массиву символов.Тем не менее, структуры (даже те, которые содержат символьные массивы) - это еще один источник рыбы.

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

typedef struct
{
    char value[100];
} string;

int main()
{
    string a = {"hello"};
    a = (string){"another string!"}; // overwrite value with a new string
    puts(a.value);

    string b = {"a NEW string"};
    b = a; // override with the value of another "string" struct
    puts(b.value); // prints "another string!" again
}

Итак, в вашем исходном примере должен скомпилироваться следующий код:

typedef struct{
    char a[6];
} point;

int main()
{
   point p;

   // note that only 5 characters + 1 for '\0' will fit in a char[6] array.
   p = (point){"onetw"};
}
1 голос
/ 11 января 2012

Нет необходимости в strcpy или C99. Пример в чистом ANSI C:

typedef struct{
   char a[6];
} point;

int main()
{
   point p;
   *(point*)p.a = *(point*)"onetwo";
   fwrite(p.a,6,1,stdout);fflush(stdout);
   return 0;
}
1 голос
/ 13 августа 2010

Обратите внимание, что для того, чтобы сохранить строку «onetwo» в вашем массиве, она должна иметь длину [7], а не такую, как написано в вопросе.Дополнительный символ предназначен для хранения терминатора '\ 0'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...