Почему я не могу инициализировать массив строк как этот? - PullRequest
2 голосов
/ 16 февраля 2010
char sXSongBuffer[20][30];
sXSongBuffer = {"Thriller", "Don't Stop Till You Get Enough", "Billy Jean"};

Почему это возвращает ошибку expected expression before ‘{’ token? Причина, по которой я хочу инициализировать свой массив таким образом, заключается в том, что я могу изменить его содержимое следующим образом:

sXSongBuffer = {"New Song", "More Music From Me"};

Ответы [ 4 ]

6 голосов
/ 16 февраля 2010

Вы не можете назначать массивы в C. C позволяет инициализировать массивы значениями, которые являются константами времени компиляции. Если вы хотите изменить значения позже или установить значения, которые не являются константами времени компиляции, вы должны назначить определенный индекс массива вручную.

Итак, ваше присвоение sXSongBuffer запрещено в C. Более того, поскольку sXSongBuffer[0] - sXSongBuffer[19] также являются массивами, вы даже не можете сказать: sXSongBuffer[0] = "New Song";

В зависимости от того, что вы хотите, это может работать для вас:

/* declare sXSongBuffer as an array of pointers */
char *sXSongBuffer[30] = {
    "Thriller",
    "Don't Stop Till You Get Enough",
    "Billy Jean",
    NULL /* set the rest of the elements to NULL */
};
size_t i;
/* and then later in your code */
sXSongBuffer[0] = "New Song";
sXSongBuffer[1] = "More Music From Me";
for (i=2; i < sizeof sXSongBuffer; ++i)
    sXSongBuffer[i] = NULL;

Но вышесказанное работает, только если вы знаете все свои строки во время компиляции. Если нет, вам придется решить, хотите ли вы использовать «достаточно большие» массивы или вам нужна динамическая память для строк и / или количества строк. В обоих случаях вы захотите использовать эквивалент strcpy() для копирования ваших строк.

Редактировать : Чтобы ответить на комментарий:

Вы объявляете массив из 30 указателей на символы с первыми тремя элементами, указывающими на буферы размера строк, т.е. бафф, на который указывает sXSongBuffer[0], не будет содержать строку больше "Thriller", и если он sXSongBuffer[0] = malloc(32); Он получит небольшой порей памяти. Кроме того, ему потребуется malloc памяти для каждого из остальных слотов в массиве. Он должен либо использовать двумерные символьные массивы, как в OP + назначенный init, либо malloc каждый буфер во время выполнения и копировать значения. Ему также нужно будет запомнить free любую память, которую он malloc s.

sXSongBuffer в char *sXSongBuffer[30]; - это массив размера 30, каждый элемент которого представляет собой char *, указатель на char. Когда я делаю:

char *sXSongBuffer[30];

каждый из этих 30 указателей неинициализирован. Когда я делаю:

char *sXSongBuffer[30] = { "Thriller", ... };

Я установил указатели на разные места только для чтения. Ничто не мешает мне затем «перенаправить» указатели куда-то еще. Это как если бы я имел:

char *data = "Hello";
printf("%s\n", data);
data = "Hello, world";
printf("%s\n", data);

В приведенном выше фрагменте я сначала назначаю data на "Hello", а затем изменяю его, чтобы он указывал на более длинную строку. Код, приведенный выше в моем ответе, не сделал ничего, кроме переназначения sXSongBuffer[i] на что-то еще позже, и, поскольку sXSongBuffer[i] - указатель, назначение в порядке. В частности, sXSongBuffer[0] является char * и может указывать на любое допустимое местоположение, в котором есть char.

Как я сказал позже в моем ответе, если строки не известны во время компиляции, эта схема не работает, и нужно либо использовать массивы с "достаточно большими" размерами, либо динамически распределять память, которая велика достаточно.

0 голосов
/ 16 февраля 2010

Взгляните на Назначенные инициализаторы .

#include <stdio.h>

int main (void) {

    char a[6][6] = { [2] = "foo", [4] = "bar" };

    for (int i=0; i<6; ++i)
        printf("%d == %s\n", i, a[i]);

    return 0;
}

Это функция c99.Компилировать с:

gcc -W -std=c99 2dInit.c -o 2dInit

Это выводит:

0 == 
1 == 
2 == foo
3 == 
4 == bar
5 == 

В вашем случае вы хотите сделать:

char sXSongBuffer[20][30] = { 
    [0] = "Thriller", 
    [1] = "Don't Stop Till You Get Enough", 
    [2] = "Billy Jean"
};
0 голосов
/ 16 февраля 2010

Вы не можете просто написать

char sXSongBuffer[20][30];
sXSongBuffer = {"Thriller", "Don't Stop Till You Get Enough", "Billy Jean"};

Вы должны либо инициализировать массив сразу (но он будет содержать только 3 элемента):

char * sXSongBuffer[]= {"Thriller", "Don't Stop Till You Get Enough", "Billy Jean"};

Или используйте stnrcpy для каждого предмета:

char sXSongBuffer[20][30];
strncpy(sXSongBuffer[0],"Thriller",29);
strncpy(sXSongBuffer[1],"Don't Stop Till You Get Enough",29);
strncpy(sXSongBuffer[2],"Billy Jean",29);
0 голосов
/ 16 февраля 2010

C не имеет литералов массива общего назначения. Синтаксис списка {} работает только при инициализации, то есть при присвоении значения в том же операторе, который объявляет переменную.

...