Простое объявление / вопрос о назначении массива C

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

int values[3];

if(1)
   values = {1,2,3};

printf("%i", values[0]);

Спасибо.


person Daniel Wood    schedule 17.10.2009    source источник
comment
См. Здесь некоторые идеи: stackoverflow.com/questions/1223736/   -  person Karl Voigtland    schedule 17.10.2009


Ответы (8)


вы можете объявить статический массив с данными для инициализации:

static int initvalues[3] = {1,2,3};
…
if(1)
    memmove(values,initvalues,sizeof(values));
person Michael Krelin - hacker    schedule 17.10.2009
comment
Могу я не делать memmove (values, {1,2,3}, sizeof (values)); ? - person Daniel Wood; 17.10.2009
comment
Нет, так нельзя. - person hlovdal; 17.10.2009
comment
Думаю, вы могли бы: memmove (values, (int [3]) {1,2,3}, sizeof (int [3])); Смотрите мой ответ ниже. - person Karl Voigtland; 17.10.2009
comment
Здесь нет необходимости использовать memmove поверх memcpy - массивы точно не перекрываются. - person caf; 18.10.2009
comment
Как вы думаете, почему я использовал memmove вместо memcpy? Я просто использовал memmove. ;-) - person Michael Krelin - hacker; 18.10.2009
comment
@Michael: @caf имел в виду, что в данном сценарии нет необходимости перемещать память, потому что source и dest не перекрываются. Таким образом, memcpy может быть немного быстрее. См. Этот http://stackoverflow.com/questions/1201319/what-is-the-difference-between-memmove-and-memcpy - person jweyrich; 03.08.2010

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

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

После объявления вам нужно будет присвоить каждое значение индивидуально, т.е.

if (1) 
{
  values[0] = 1;
  values[1] = 2;
  values[2] = 3;
}

Или вы можете использовать цикл, в зависимости от того, какие значения вы хотите использовать.

if (1)
{
  for (i = 0 ; i < 3 ; i++)
  { 
    values[i] = i+1;
  }
}
person Mark Rushakoff    schedule 17.10.2009
comment
Это работает для 3 значений, но что, если бы у меня был массив с 50 значениями? - person Daniel Wood; 17.10.2009
comment
Затем вы использовали бы цикл или _1 _ / _ 2_, как @hacker предлагает в другом ответе. - person Mark Rushakoff; 17.10.2009
comment
memcpy кажется самым аккуратным. Спасибо за вашу помощь. - person Daniel Wood; 17.10.2009

В C99, используя составные литералы, вы могли:

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

or

int* values = (int[3]){1, 2, 3};
person Karl Voigtland    schedule 17.10.2009
comment
+1; имейте в виду, что в последнем случае массив будет иметь автоматическую продолжительность хранения, то есть возвращение его из функции приведет к тому, что вас съест грустный - person Christoph; 17.10.2009
comment
Кристоф, будет ли это означать, что memmove извлечение из такого массива потребует сначала его инициализации в автоматическом хранилище, а затем его копирования? - person Michael Krelin - hacker; 17.10.2009
comment
@hacker: в принципе, да, на практике компилятор оптимизирует его прочь (для gcc достаточно -O1) - person Christoph; 17.10.2009
comment
С другой стороны, вы уверены, что это действительно автоматическое хранение? Разве это не похоже на строковые литералы? Или использование ключевого слова const заставит его вести себя так же, как и строковые литералы? - person Michael Krelin - hacker; 17.10.2009
comment
@hacker: да, const составные литералы могут использоваться так же, как и строки (это деталь реализации, не имеющая отношения к семантике языка); неконстантные литералы гарантированно будут отличаться для каждой записи в включающем блоке - person Christoph; 17.10.2009
comment
Да, но теперь, когда я думаю об этом, я не думаю, что когда-либо видел неконстантные литералы в C раньше ... - person Michael Krelin - hacker; 18.10.2009
comment
Также имейте в виду, как отвечал ответчик, что это C99, а не более популярный ISO C90. - person BobbyShaftoe; 18.10.2009

Также возможно скрыть memcpy, используя блочную копию структур компилятора. Это делает код уродливым из-за всех .i и i :, но, возможно, это решает вашу конкретную проблему.

typedef struct {
    int i[3];
} inta;

int main()
{
    inta d = {i:{1, 2, 3}};

    if (1)
        d = (inta){i:{4, 5, 6}};

    printf("%d %d %d\n", d.i[0], d.i[1], d.i[2]);

    return 0;
}
person eyalm    schedule 18.10.2009

Есть еще такая ... :)

char S[16]="";
strncpy(S,"Zoodlewurdle...",sizeof(S)-1);

Проверьте, что произойдет, если вы объявите S [8] или S [32], чтобы понять, почему это так эффективно.

Я написал свои собственные строковые функции, основанные на логике strlcpy OpenBSD, направленные на обеспечение того, чтобы байт терминатора ДОЛЖЕН существовать в случае переполнения, а стандартный strncpy не будет этого делать, поэтому вы должны внимательно следить за тем, как вы его используете.

Вышеупомянутый метод эффективен, потому что объявление ="" at гарантирует 0 байтов повсюду, а sizeof(S)-1 гарантирует, что если вы переборщите со строкой в ​​кавычках, переданной в strncpy, вы получите усечение и отсутствие нарушения последнего 0 байта, поэтому теперь это безопасно от переполнения, И при доступе к строке позже. Я нацелил это на ANSI C, поэтому он должен быть безопасным где угодно.

person Lostgallifreyan    schedule 17.03.2012
comment
Я понимаю, что это строка, а не массив целых чисел, но может быть способ соответствующим образом преобразовать метод без написания собственного кода итерации. - person Lostgallifreyan; 17.03.2012
comment
strncpy для символьных массивов, как ___ для целочисленных массивов? - person Keith Thompson; 31.07.2016

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

#include <stdio.h>

struct wrapper { int array[3]; };

int main(){
    struct wrapper a;
    struct wrapper b = {{1, 2, 3}};

    a = b;

    printf("%i %i %i", a.array[0], a.array[1], a.array[2]);

    return 0;
}
person GRAYgoose124    schedule 22.01.2013

Это работает и оптимизируется лучше в gcc с -O3 (компилятор полностью удаляет код), тогда как memcpy заставляет копировать память во всех случаях.

template <typename Array>
struct inner
{
    Array x;
};


template <typename Array>
void assign(Array& lhs, const Array& rhs)
{
    inner<Array>& l( (inner<Array>&)(lhs));
    const inner<Array>& r( (inner<Array>&)(rhs));
    l = r;
}

int main()
{
    int x[100];
    int y[100];

    assign(x, y);
}
person Matthew Herrmann    schedule 03.08.2010
comment
Вопрос помечен как C, а не C ++. Этот ответ написан на C ++ и полностью недействителен в C. - person Jonathan Leffler; 31.07.2016

person    schedule
comment
вы также можете выполнить цикл sscanf из функции, а затем вернуть массив - person frozenat99; 31.07.2016
comment
Добро пожаловать в Stack Overflow. Вскоре прочтите страницу О программе. Когда вы отвечаете на вопрос более чем через 6 лет после того, как его задали (и он получил одобренные и принятые ответы), вы должны добавить что-то особенное - новый подход или, возможно, продукт изменился с тех пор, как были даны исходные ответы. К счастью для вас, ни один из других ответов не предлагает анализировать строковое представление значений массива - так что все в порядке. Не уверен, что это хороший механизм, но он другой. Ваш вызов malloc() не выделяет достаточно места на любом компьютере, где sizeof(char) != sizeof(int). - person Jonathan Leffler; 31.07.2016
comment
отредактированный malloc, если использование строк не работает, вы также можете использовать функции из stdarg.h - person frozenat99; 31.07.2016