Как инициализировать все члены массива одним и тем же значением?


968

У меня есть большой массив в C (не C ++, если это имеет значение). Я хочу инициализировать все элементы с одинаковым значением.

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


16
Пока что ни в одном из ответов не упоминается обозначенная инициализирующая нотация, которая возможна для C99 и выше. Например: enum { HYDROGEN = 1, HELIUM = 2, CARBON = 6, NEON = 10, … };и struct element { char name[15]; char symbol[3]; } elements[] = { [NEON] = { "Neon", "Ne" }, [HELIUM] = { "Helium", "He" }, [HYDROGEN] = { "Hydrogen", "H" }, [CARBON] = { "Carbon", "C" }, … };. Если вы удалите многоточие , эти фрагменты будут скомпилированы в C99 или C11.
Джонатан Леффлер

На самом деле ответ abelenky использует назначенный инициализатор, но не полностью сформированный код инициализации
Rob11311

memset () может помочь, но зависит от значения.
Ник

2
memset()конкретное обсуждение: stackoverflow.com/questions/7202411/… Я думаю, что это работает только для 0.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Ответы:


1239

Если это значение не равно 0 (в этом случае вы можете опустить некоторую часть инициализатора и соответствующие элементы будут инициализированы равными 0), простого пути не существует.

Не забывайте об очевидном решении, хотя:

int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };

Элементы с пропущенными значениями будут инициализированы в 0:

int myArray[10] = { 1, 2 }; // initialize to 1,2,0,0,0...

Так что это инициализирует все элементы в 0:

int myArray[10] = { 0 }; // all elements 0

В C ++ пустой список инициализации также инициализирует каждый элемент в 0. Это не разрешено с C:

int myArray[10] = {}; // all elements 0 in C++

Помните, что объекты со статической длительностью хранения будут инициализированы в 0, если не указан инициализатор:

static int myArray[10]; // all elements 0

И то, что «0» не обязательно означает «все биты-ноль», поэтому использование вышеупомянутого лучше и более переносимо, чем memset (). (Значения с плавающей точкой будут инициализированы в +0, указатели на нулевое значение и т. Д.)


27
Читая стандарт C ++, вы также можете сделать int array [10] = {}; к нулю инициализировать. У меня нет стандарта C, чтобы проверить, что это действительный C, хотя.
workmad3

54
Глядя на раздел 6.7.8 Инициализация стандарта C99, не похоже, что пустой список инициализатора разрешен.
Джонатан Леффлер

7
C99 имеет много приятных функций для инициализации структуры и массива; единственная особенность, которой у него нет (но у Fortran IV, 1966), это способ повторить определенный инициализатор для массива.
Джонатан Леффлер

8
@CetinSert: Что вы имеете в виду, что это не работает? Он делает именно то, что говорит этот ответ, он должен делать. Он не делает то, что говорит комментарий в вашем коде, но этот комментарий неверен.
Бенджамин Линдли

9
@CetinSert: Вы единственный, кто заявил в этом комментарии, что все элементы будут установлены в -1. Этот ответ справедливо утверждает, что все неопределенные элементы обнуляются. Результаты вашего кода соответствуют этой претензии.
Бенджамин Линдли

394

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

int array[1024] = {[0 ... 1023] = 5};

Ознакомьтесь с подробным описанием: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html


12
И этот синтаксис вызывает огромное увеличение размера файла скомпилированных двоичных файлов. Для N = 65536 (вместо 1024) размер моего двоичного файла увеличивается с 15 КБ до 270 КБ !!
Цетин Серт

50
@CetinSert Compiler должен добавить 65536 intс в статические данные, что составляет 256 К - именно то увеличение размера, которое вы наблюдали.
2013 года

15
@CetinSert Почему я должен? Это стандартное поведение компилятора, не специфичное для обозначенных инициализаторов. Если вы статически инициализируете 65536 intс, например, int foo1 = 1, foo2 = 1, ..., foo65536 =1;вы получите такое же увеличение размера.
2013 г.

27
еще лучше: "int array [] = {[0 ... 1023] = 5}", размер массива будет автоматически установлен равным 1024, его будет проще и безопаснее изменять.
Франсуа

4
@Francois или для двумерного массива, bool array[][COLS] = { [0...ROWS-1][0...COLS-1] = true}хотя я не уверен, что это более читабельно, чем полная форма.
g33kz0r

178

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

#define VAL_1X     42
#define VAL_2X     VAL_1X,  VAL_1X
#define VAL_4X     VAL_2X,  VAL_2X
#define VAL_8X     VAL_4X,  VAL_4X
#define VAL_16X    VAL_8X,  VAL_8X
#define VAL_32X    VAL_16X, VAL_16X
#define VAL_64X    VAL_32X, VAL_32X

int myArray[53] = { VAL_32X, VAL_16X, VAL_4X, VAL_1X };

Если вам нужно изменить значение, вы должны сделать замену только в одном месте.

Редактировать: возможные полезные расширения

(любезно предоставлено Джонатаном Леффлером )

Вы можете легко обобщить это с помощью:

#define VAL_1(X) X
#define VAL_2(X) VAL_1(X), VAL_1(X)
/* etc. */

Вариант может быть создан с использованием:

#define STRUCTVAL_1(...) { __VA_ARGS__ }
#define STRUCTVAL_2(...) STRUCTVAL_1(__VA_ARGS__), STRUCTVAL_1(__VA_ARGS__)
/*etc */ 

это работает со структурами или составными массивами.

#define STRUCTVAL_48(...) STRUCTVAL_32(__VA_ARGS__), STRUCTVAL_16(__VA_ARGS__)

struct Pair { char key[16]; char val[32]; };
struct Pair p_data[] = { STRUCTVAL_48("Key", "Value") };
int a_data[][4] = { STRUCTVAL_48(12, 19, 23, 37) };

имена макросов являются предметом переговоров.


12
Я хотел бы рассмотреть это только в крайних случаях, конечно, memset - более элегантный способ выразить это.
u0b34a0f6ae

47
Если данные должны быть в ПЗУ, memset использовать нельзя.
Профессор Фалькен нарушил контракт

9
Препроцессор фактически сгенерирует код из #defines. При больших размерах массива исполняемый размер будет увеличиваться. Но определенно + за идею;)
Леонид

7
@ Alcott, на старых компьютерах и во многих встроенных системах код в конечном итоге помещается в EPROM или ROM . ROM-способность во встроенных системах также стала означать «код, помещенный во флэш-память», поскольку она имеет примерно те же последствия, а именно то, что память не может быть записана во время выполнения. Т.е. memset или любая другая инструкция по обновлению или изменению памяти не может быть использована. Константы, тем не менее, могут быть выражены и мигать или записываться в ПЗУ до запуска программы.
Профессор Фалькен нарушил контракт

4
@ u0b34a0f6ae: Имейте в виду, что вы можете использовать этот метод также, если VAL_1Xэто не одно целое число, а список. Подобно состояниям Amigable, это также путь для встроенных систем, в которых вы хотите определить значения инициализации EEPROM или флэш-памяти. В обоих случаях вы не можете использовать memset().
Мартин Шаррер

63

Если вы хотите, чтобы каждый член массива был явно инициализирован, просто пропустите измерение из объявления:

int myArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

Компилятор выведет измерение из списка инициализатора. К сожалению, для многомерных массивов только самое внешнее измерение может быть опущено:

int myPoints[][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };

хорошо, но

int myPoints[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };

не является.


это правильно ? int myPoints[10][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
Правин Говда IV

10
Нет. Вы опускаете самое внутреннее измерение, которое не допускается. Это даст ошибку компилятора.
Фрэнк Щерба

4
И инициализаторы, и определение длины были введены в C99.
Палек

3
@Palec: Нет - вывод длины в C был со времен предстандартного C (с момента публикации K & R 1st Edition, и, возможно, некоторое время назад). Назначенные инициализаторы были новыми в C99, но они не используют назначенные инициализаторы.
Джонатан Леффлер

53

Я видел некоторый код, который использовал этот синтаксис:

char* array[] = 
{
    [0] = "Hello",
    [1] = "World"
};   

Где это становится особенно полезным, если вы создаете массив, который использует перечисления в качестве индекса:

enum
{
    ERR_OK,
    ERR_FAIL,
    ERR_MEMORY
};

#define _ITEM(x) [x] = #x

char* array[] = 
{
    _ITEM(ERR_OK),
    _ITEM(ERR_FAIL),
    _ITEM(ERR_MEMORY)
};   

Это поддерживает порядок, даже если вы пишете некоторые из перечисляемых значений не по порядку.

Подробнее об этой технике можно узнать здесь и здесь .


8
Это синтаксис инициализатора C99, уже описанный в некоторых других ответах. Вы могли бы с пользой сделать заявление char const *array[] = { ... };или даже char const * const array[] = { ... };не так ли?
Джонатан Леффлер

22
int i;
for (i = 0; i < ARRAY_SIZE; ++i)
{
  myArray[i] = VALUE;
}

Я думаю это лучше чем

int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5...

Incase размер массива изменений.


12
Для справки, это в основном более медленная, более многословная версияmemset(myArray, VALUE, ARRAY_SIZE);
Benson

18
Как бы вы использовали memset для инициализации массива int с некоторым значением больше 255? memset работает только если размер массива в байтах.
Мэтт

21
@Benson: Вы не можете заменить вышеуказанный код на memset на платформах, где sizeof (int)> sizeof (char). Попробуй это.
ChrisWue

13

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

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

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


Не могли бы вы добавить пример использования этого memsetдля инициализации массива?
Сопалахо де Арриерес

8

Вот еще один способ:

static void
unhandled_interrupt(struct trap_frame *frame, int irq, void *arg)
{
    //this code intentionally left blank
}

static struct irqtbl_s vector_tbl[XCHAL_NUM_INTERRUPTS] = {
    [0 ... XCHAL_NUM_INTERRUPTS-1] {unhandled_interrupt, NULL},
};

Видеть:

C-расширения

Назначенные единицы

Затем задайте вопрос: когда можно использовать расширения C?

Пример кода выше находится во встроенной системе и никогда не увидит свет от другого компилятора.


6

Для инициализации «нормальных» типов данных (таких как массивы int) вы можете использовать скобочную запись, но она обнулит значения после последней, если в массиве еще есть место:

// put values 1-8, then two zeroes
int list[10] = {1,2,3,4,5,6,7,8};

5

Если массив имеет тип int или что-либо с размером int или размер вашего mem-шаблона соответствует точному времени в int (т.е. все нули или 0xA5A5A5A5), лучшим способом является использование memset () .

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


5

Слегка насмешливый ответ; написать заявление

array = initial_value

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


4

Существует быстрый способ инициализации массива любого типа с заданным значением. Это работает очень хорошо с большими массивами. Алгоритм заключается в следующем:

  • инициализировать первый элемент массива (обычным способом)
  • скопировать часть, которая была установлена ​​на часть, которая не была установлена, удваивая размер с каждой следующей операцией копирования

Для массива 1 000 000элементов intэто в 4 раза быстрее обычной инициализации цикла (i5, 2 ядра, 2,3 ГГц, 4 ГБ памяти, 64 бита):

loop runtime 0.004248 [seconds]

memfill() runtime 0.001085 [seconds]


#include <stdio.h>
#include <time.h>
#include <string.h>
#define ARR_SIZE 1000000

void memfill(void *dest, size_t destsize, size_t elemsize) {
   char   *nextdest = (char *) dest + elemsize;
   size_t movesize, donesize = elemsize;

   destsize -= elemsize;
   while (destsize) {
      movesize = (donesize < destsize) ? donesize : destsize;
      memcpy(nextdest, dest, movesize);
      nextdest += movesize; destsize -= movesize; donesize += movesize;
   }
}    
int main() {
    clock_t timeStart;
    double  runTime;
    int     i, a[ARR_SIZE];

    timeStart = clock();
    for (i = 0; i < ARR_SIZE; i++)
        a[i] = 9;    
    runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
    printf("loop runtime %f [seconds]\n",runTime);

    timeStart = clock();
    a[0] = 10;
    memfill(a, sizeof(a), sizeof(a[0]));
    runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
    printf("memfill() runtime %f [seconds]\n",runTime);
    return 0;
}

2
Извините, но это не так. Может быть, вы забыли включить оптимизацию компиляции во время тестов (проверено в режиме отладки?). Если я проверяю это, цикл почти всегда на 50% быстрее, чем memfill («всегда» из-за некоторых скачков нагрузки на моем компьютере). И используя memset (a, 0, sizeof (a)); даже в два раза быстрее, чем loopfill.
RS1980

2
Как и в случае с любым другим кодом, вам нужно быть предельно осторожным. Добавление цикла для выполнения временного кода 10 раз (и удвоение размера массива до 20M) показывает - для меня, запуск на MacBook Pro с macOS Sierra 10.12.3 и использование GCC 6.3.0 - что в первый раз, используя цикл занимает около 4600 мкс, а memfill()код - около 1200 мкс. Однако на последующих итерациях цикл занимает около 900-1000 мкс, а memfill()код - 1000-1300 мкс. На первую итерацию, вероятно, влияет время заполнения кеша. Обратный тесты и memfill()медленный первый раз.
Джонатан Леффлер

2

Никто не упомянул порядок индексов для доступа к элементам инициализированного массива. Мой пример кода даст наглядный пример.

#include <iostream>

void PrintArray(int a[3][3])
{
    std::cout << "a11 = " << a[0][0] << "\t\t" << "a12 = " << a[0][1] << "\t\t" << "a13 = " << a[0][2] << std::endl;
    std::cout << "a21 = " << a[1][0] << "\t\t" << "a22 = " << a[1][1] << "\t\t" << "a23 = " << a[1][2] << std::endl;
    std::cout << "a31 = " << a[2][0] << "\t\t" << "a32 = " << a[2][1] << "\t\t" << "a33 = " << a[2][2] << std::endl;
    std::cout << std::endl;
}

int wmain(int argc, wchar_t * argv[])
{
    int a1[3][3] =  {   11,     12,     13,     // The most
                        21,     22,     23,     // basic
                        31,     32,     33  };  // format.

    int a2[][3] =   {   11,     12,     13,     // The first (outer) dimension
                        21,     22,     23,     // may be omitted. The compiler
                        31,     32,     33  };  // will automatically deduce it.

    int a3[3][3] =  {   {11,    12,     13},    // The elements of each
                        {21,    22,     23},    // second (inner) dimension
                        {31,    32,     33} };  // can be grouped together.

    int a4[][3] =   {   {11,    12,     13},    // Again, the first dimension
                        {21,    22,     23},    // can be omitted when the 
                        {31,    32,     33} };  // inner elements are grouped.

    PrintArray(a1);
    PrintArray(a2);
    PrintArray(a3);
    PrintArray(a4);

    // This part shows in which order the elements are stored in the memory.
    int * b = (int *) a1;   // The output is the same for the all four arrays.
    for (int i=0; i<9; i++)
    {
        std::cout << b[i] << '\t';
    }

    return 0;
}

Выход:

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

11      12      13      21      22      23      31      32      33

4
<iostream>не действует , Cкак std::cout, std::cinи т.д. является частью std::namespaceи Cне поддерживает namespaces. Попробуйте использовать <stdio.h>для printf(...)вместо.
Фрэнсис Куглер

2

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

int i,value=5,array[1000]; 
for(i=0;i<1000;i++) array[i]=value; 

Дополнительный бонус: код на самом деле разборчивый :)


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

Совершенно бесполезно для большой статической таблицы поиска внутри функции, вызываемой много раз.
Мартин Боннер поддерживает Монику

... не вспоминайте, что статические таблицы поиска внутри функций были частью первоначального вопроса - сделайте это простым. Тем не менее, @Community, вероятно, прибил его.
JWDN

1
  1. Если ваш массив объявлен как статический или является глобальным, все элементы в массиве уже имеют значение по умолчанию 0.
  2. Некоторые компиляторы устанавливают для массива значение по умолчанию 0 в режиме отладки.
  3. По умолчанию легко установить значение 0: int array [10] = {0};
  4. Однако для других значений вы должны использовать memset () или loop;

пример: массив int [10]; memset (массив, -1, 10 * sizeof (int));


0
#include<stdio.h>
int main(){
int i,a[50];
for (i=0;i<50;i++){
    a[i]=5;// set value 5 to all the array index
}
for (i=0;i<50;i++)
printf("%d\n",a[i]);
   return 0;
}

Это даст o / p 5 5 5 5 5 5 ...... до размера всего массива


0

Я знаю, что пользователь Tarskiответил на этот вопрос аналогичным образом, но я добавил еще несколько деталей. Простите за мой C, потому что я немного устала от этого, так как больше склоняюсь к тому, чтобы использовать C ++, но здесь все кончено.


Если вы знаете размер массива раньше времени ...

#include <stdio.h>

typedef const unsigned int cUINT;
typedef unsigned int UINT;

cUINT size = 10;
cUINT initVal = 5;

void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal );
void printArray( UINT* myArray ); 

int main() {        
    UINT myArray[size]; 
    /* Not initialized during declaration but can be
    initialized using a function for the appropriate TYPE*/
    arrayInitializer( myArray, size, initVal );

    printArray( myArray );

    return 0;
}

void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal ) {
    for ( UINT n = 0; n < size; n++ ) {
        myArray[n] = initVal;
    }
}

void printArray( UINT* myArray ) {
    printf( "myArray = { " );
    for ( UINT n = 0; n < size; n++ ) {
        printf( "%u", myArray[n] );

        if ( n < size-1 )
            printf( ", " );
    }
    printf( " }\n" );
}

Есть несколько предостережений выше; один из них заключается в том, что UINT myArray[size];он не инициализируется непосредственно при объявлении, однако следующий блок кода или вызов функции инициализирует каждый элемент массива тем же значением, которое вы хотите. Другое предостережение: вам нужно будет написать initializing functionдля каждого, который typeвы будете поддерживать, и вам также придется изменить printArray()функцию для поддержки этих типов.


Вы можете попробовать этот код с онлайн-компилятором, найденным здесь .


0

Для отложенной инициализации (т.е. инициализации конструктора члена класса) рассмотрите:

int a[4];

unsigned int size = sizeof(a) / sizeof(a[0]);
for (unsigned int i = 0; i < size; i++)
  a[i] = 0;

0

Я знаю, что в первоначальном вопросе явно упоминается C, а не C ++, но если вы (как и я) пришли сюда в поисках решения для массивов C ++, вот интересный трюк:

Если ваш компилятор поддерживает выражения сгиба , вы можете использовать магию шаблона и std::index_sequenceсгенерировать список инициализаторов со значением, которое вы хотите. И вы можете даже constexprэто и почувствовать себя боссом

#include <array>

/// [3]
/// This functions's only purpose is to ignore the index given as the second
/// template argument and to always produce the value passed in.
template<class T, size_t /*ignored*/>
constexpr T identity_func(const T& value) {
    return value;
}

/// [2]
/// At this point, we have a list of indices that we can unfold
/// into an initializer list using the `identity_func` above.
template<class T, size_t... Indices>
constexpr std::array<T, sizeof...(Indices)>
make_array_of_impl(const T& value, std::index_sequence<Indices...>) {
    return {identity_func<T, Indices>(value)...};
}

/// [1]
/// This is the user-facing function.
/// The template arguments are swapped compared to the order used
/// for std::array, this way we can let the compiler infer the type
/// from the given value but still define it explicitly if we want to.
template<size_t Size, class T>
constexpr std::array<T, Size> 
make_array_of(const T& value) {
    using Indices = std::make_index_sequence<Size>;
    return make_array_of_impl(value, Indices{});
}

// std::array<int, 4>{42, 42, 42, 42}
constexpr auto test_array = make_array_of<4/*, int*/>(42);
static_assert(test_array[0] == 42);
static_assert(test_array[1] == 42);
static_assert(test_array[2] == 42);
static_assert(test_array[3] == 42);
// static_assert(test_array[4] == 42); out of bounds

Вы можете взглянуть на код на работе (в Wandbox)


-1

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

#include <string.h> 

void array_init( void *start, size_t element_size, size_t elements, void *initval ){
  memcpy(        start,              initval, element_size              );
  memcpy( (char*)start+element_size, start,   element_size*(elements-1) );
}

// testing
#include <stdio.h> 

struct s {
  int a;
  char b;
} array[2][3], init;

int main(){
  init = (struct s){.a = 3, .b = 'x'};
  array_init( array, sizeof(array[0][0]), 2*3, &init );

  for( int i=0; i<2; i++ )
    for( int j=0; j<3; j++ )
      printf("array[%i][%i].a = %i .b = '%c'\n",i,j,array[i][j].a,array[i][j].b);
}

Результат:

array[0][0].a = 3 .b = 'x'
array[0][1].a = 3 .b = 'x'
array[0][2].a = 3 .b = 'x'
array[1][0].a = 3 .b = 'x'
array[1][1].a = 3 .b = 'x'
array[1][2].a = 3 .b = 'x'

РЕДАКТИРОВАТЬ: start+element_sizeизменено на(char*)start+element_size


1
Я сомневаюсь, является ли это решением. Я не уверен, sizeof(void)является ли это действительным.
Крис Латс

3
Не работает Только первые два инициализируются, остальные все неинициализированы. Я использую GCC 4.0 на Mac OS X 10.4.
Dreamlax

Это вызывает неопределенное поведение, потому что исходные данные во втором memcpy()перекрываются с местом назначения. При наивной реализации memcpy()он может работать, но не обязательно, чтобы система работала.
Джонатан Леффлер

-1

В свое время (и я не говорю, что это хорошая идея), мы установили первый элемент, а затем:

memcpy (&element [1], &element [0], sizeof (element)-sizeof (element [0]);

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


Это не будет работать надежно. ИМХО, Стандарт должен был предоставлять функции, которые были бы похожи, memcpyно указывали порядок копирования снизу вверх или сверху вниз в случае наложения, но это не так.
суперкат

Как я уже сказал, мы просто не работали надежно, но в то время мы больше фокусировались на эффективности, чем на недокументированных функциях. Хотя копирование памяти более эффективно, в спецификации ничего не сказано, что она не может копировать ее в обратном порядке, в случайном порядке или разделять на несколько потоков. memmove () предоставляет возможность копировать без столкновений.
Майк

Это эквивалентно коду в другом ответе - и ошибочно. Использование memmove()не делает это работает.
Джонатан Леффлер

-2

Если вы имеете в виду параллельно, я думаю, что оператор запятой при использовании в сочетании с выражением может сделать это:

a[1]=1, a[2]=2, ..., a[indexSize]; 

или если вы имеете в виду в одной конструкции, вы можете сделать это в цикле for:

for(int index = 0, value = 10; index < sizeof(array)/sizeof(array[0]); index++, value--)
  array[index] = index;

// Обратите внимание, что оператор запятой в списке аргументов не является параллельным оператором, описанным выше;

Вы можете инициализировать замедление массива:

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

Вы можете вызвать malloc / calloc / sbrk / alloca / etc для выделения фиксированной области памяти для объекта:

int *array = malloc(sizeof(int)*numberOfListElements/Indexes);

и получить доступ к членам по:

*(array + index)

И т.п.


Оператор запятой номинально гарантирует оценку слева направо. Если в выражениях нет побочных эффектов, то может быть возможно распараллелить операции, но для компилятора было бы необычно это сделать.
Джонатан Леффлер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.