Инициализация массива C во время, отличное от объявления? - PullRequest
17 голосов
/ 05 марта 2012

Я знаю в C, что могу сделать следующее.

int test[5] = {1, 2, 3, 4, 5};

Теперь это допустимо только при объявлении массива.Однако мне было интересно, почему это не разрешено делать позже?Но потом в программе не разрешается делать следующее.

test[5] = {10, 20, 30, 40, 50}; 

или что-то подобное.Почему это?Я знаю, что это не законно, и я не жалуюсь, но кто-то может дать мне более техническое объяснение, почему я не могу этого сделать?(т.е. не просто говорите, что спецификация C не допускает этого или что-то в этом роде)

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

Спасибо, ребята

Ответы [ 5 ]

19 голосов
/ 05 марта 2012

Это не просто массивы, вы не можете предоставить инициализатор для чего-либо в любой точке, кроме определения.Люди иногда называют второе утверждение чего-то вроде int i; i = 0; «инициализацией i».Фактически это присваивание i, которое ранее содержало неопределенное значение, потому что оно не было инициализировано.Очень редко бывает сложно назвать это «инициализацией», но в том, что касается языка, там нет инициализатора.

Назначение и инициализация - это разные вещи для языка, хотя они оба используют символ =,Массивы не могут быть назначены.

Причина, по которой массивы не могут быть назначены, описана в другом месте, например Почему C ++ поддерживает членское присвоение массивов внутри структур, но не в целом? .Краткий ответ: «исторические причины».Я не думаю, что есть какая-то ужасная техническая причина, по которой язык нельзя было изменить, чтобы разрешить присвоение массива.

Существует вторичная проблема, которая грамматически {1, 2, 3, 4, 5} является инициализатором, а не литералом массива, и, следовательно, можетне будет использоваться в назначении, даже если массивы были назначаемыми.Я не совсем уверен, почему у C89 нет литералов массива, вероятно, просто никто не удосужился потребовать их.C99 вводит синтаксис «составных литералов» вообще и литералов массива в частности: (int[]) {1, 2, 3, 4, 5}.Вы все еще не можете присвоить массив из него.

6 голосов
/ 05 марта 2012

Дело в том, что использование int array[]={ } означает объявление и инициализации объекта, который вы создали.

Вы можете присваивать значения массиву после было объявлено :

int array[5];
array[0] = 1, array[1] = 2, ...

То, что вы делали, назначало несколько значений для одна отдельная запись массива:

array[5] = {1,2,3,4,5}; // array[5] can only contain one value

Вместо этого это будет законно:

array[5] = 6;

Надеюсь, это имеет смысл. Просто вопрос синтаксиса.

3 голосов
/ 28 октября 2016

Вот решение

//Declaration
int a[5];
int a_temp[5] = {1, 2, 3, 4, 5 };
memcpy(a, a_temp, sizeof(a));
//Now array a have values 1, 2, 3, 4, 5
3 голосов
/ 05 марта 2012

Обратите внимание, что составной литерал C99 позволяет вам «передавать массивы в функции»:

int your_func(int *test)
{
    ...use test as an array...
}

void other_func(void)
{
    int x = rand();
    if (your_func((int[]){ 0, 1, 2, x, 3, 4 }) > 0 ||
        your_func((int[]){ 9, x, 8, 7, 6, 5 }) > 0)
        ...whatever...
}

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

0 голосов
/ 05 марта 2012

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

double A[5];
double B[5];

в выражении, таком как

A = B;

оба уже преобразованы в указатели. A слева, в частности, не является "lvalue", поэтому вы не можете назначить его.

Это звучит как отстойное оправдание, но я думаю, что исторически это просто так происходило. C (и C ++ с ним) попали в ловушку раннего выбора синтаксиса, и если вы хотите оставаться совместимым с унаследованным кодом, то, вероятно, не так уж много выхода.

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