Объявление и инициализация массивов в C

Существует ли способ объявить сначала и затем инициализировать массив в C?

До сих пор я инициализировал массив как это:

int myArray[SIZE] = {1,2,3,4....};

Но я должен сделать что-то вроде этого

int myArray[SIZE];

myArray = {1,2,3,4....};
52
задан Jonathan Leffler 29 June 2010 в 02:59
поделиться

6 ответов

В C99 это можно сделать, используя составной литерал в сочетании с memcpy

memcpy(myarray, (int[]) { 1, 2, 3, 4 }, sizeof myarray);

(при условии, что размер источника и размер цели одинаков).

В C89/90 вы можете эмулировать это, объявив дополнительный массив "источник"

const int SOURCE[SIZE] = { 1, 2, 3, 4 }; /* maybe `static`? */
int myArray[SIZE];
...
memcpy(myarray, SOURCE, sizeof myarray);
32
ответ дан 7 November 2019 в 09:33
поделиться

Нет, вы не можете установить для них произвольные значения в одном операторе (если это не сделано как часть объявления).

Вы можете сделать это с помощью кода, например:

myArray[0] = 1;
myArray[1] = 2;
myArray[2] = 27;
:
myArray[99] = -7;

или (если есть формула):

for (int i = 0; i < 100; i++) myArray[i] = i + 1;

Другая возможность - сохранить некоторые шаблоны, которые установлены во время объявления и используйте их для инициализации вашего массива, например:

static const int onceArr[]  = {  0,  1,  2,  3,  4,..., 99};
static const int twiceArr[] = {  0,  2,  4,  6,  8,...,198};
:
int myArray[7];
:
memcpy (myArray, twiceArr, sizeof (myArray));

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


Вы даже можете локализовать его для функции инициализации:

void initMyArray (int *arr, size_t sz) {
    static const int template[] = {2, 3, 5, 7, 11, 13, 17, 19, 21, ..., 9973};
    memcpy (arr, template, sz);
}
:
int myArray[100];
initMyArray (myArray, sizeof(myArray));

Статический массив (почти наверняка) будет создан во время компиляции, поэтому для этого не будет затрат времени выполнения, и memcpy должен быть ослепительно быстрым, вероятно, быстрее, чем 1229 операторов присваивания, но определенно меньше печатать с вашей стороны :-).

13
ответ дан 7 November 2019 в 09:33
поделиться

Есть ли способ объявить первым и затем инициализировать массив в C?

Есть! но не используя описанный вами метод.

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

myArray[0] = 1;
myArray[1] = 2;
...

или

for(int i = 1; i <= SIZE; i++)
{
  myArray[i-1] = i;
}
4
ответ дан 7 November 2019 в 09:33
поделиться

Не существует такого конкретного способа инициализации массива после его однократного объявления.

Есть только три варианта:

1.) инициализировать их в разных строках:

int array[SIZE];

array[0] = 1;
array[1] = 2;
array[2] = 3;
array[3] = 4;
//...
//...
//...

Но я думаю, это не то, что вам нужно.

2.) Инициализируйте их с помощью цикла for или while:

for (i = 0; i < MAX ; i++)  {
    array[i] = i;
}

Это НАИЛУЧШИЙ СПОСОБ для достижения вашей цели.

3.) В случае, если вам нужно инициализировать массив в одной строке, вы должны определить по крайней мере массив с инициализацией. А затем скопируйте его в целевой массив, но я думаю, что это бесполезно, в этом случае вы должны определить и инициализировать свой массив в одной строке.

И я могу спросить, почему именно вы хотите это сделать ???

0
ответ дан 7 November 2019 в 09:33
поделиться

Это дополнение к принятому ответу AndreyT с комментарием Наяна о несовпадающих размерах массивов. Я не согласен с их автоматической установкой пятого элемента на ноль. Вероятно, это должно быть 5 - число после 1,2,3,4. Поэтому я бы предложил оболочку для memcpy (), чтобы выдавать ошибку времени компиляции , когда мы пытаемся скопировать массивы разных размеров:

#define Memcpy(a,b) do {                    /* copy arrays */       \
    ASSERT(sizeof(a) == sizeof(b) &&        /* a static assert */   \
           sizeof(a) != sizeof((a) + 0));   /* no pointers */       \
    memcpy((a), (b), sizeof (b));           /* & unnecesary */      \
    } while (0)                             /* no return value */

Этот макрос будет генерировать ошибку времени компиляции, если ваш массив имеет размер длина 1. Что, возможно, является особенностью.

Поскольку мы используем макрос, составной литерал C99, похоже, требует дополнительной пары круглых скобок:

Memcpy(myarray, ((int[]) { 1, 2, 3, 4 }));

Здесь ASSERT () - это «статическое утверждение». Если у вас еще нет своего, я использую следующее на нескольких платформах:

#define CONCAT_TOKENS(a, b) a ## b
#define EXPAND_THEN_CONCAT(a,b) CONCAT_TOKENS(a, b)
#define ASSERT(e) enum {EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__) = 1/!!(e)}
#define ASSERTM(e,m) /* version of ASSERT() with message */ \
    enum{EXPAND_THEN_CONCAT(m##_ASSERT_line_,__LINE__)=1/!!(e)}
2
ответ дан 7 November 2019 в 09:33
поделиться

Почему нельзя инициализировать при объявлении?

Какой компилятор Си вы используете? Поддерживает ли он C99?

Если он поддерживает C99, вы можете объявить переменную там, где она вам нужна, и инициализировать ее при объявлении.

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

1
ответ дан 7 November 2019 в 09:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: