У меня есть большой массив в C (не C ++, если это имеет значение). Я хочу инициализировать все элементы с одинаковым значением.
Я могу поклясться, что когда-то знал простой способ сделать это. Я мог бы использовать memset()
в моем случае, но не существует ли способ сделать это, встроенный прямо в синтаксис C?
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.memset()
конкретное обсуждение: stackoverflow.com/questions/7202411/… Я думаю, что это работает только для 0.Ответы:
Если это значение не равно 0 (в этом случае вы можете опустить некоторую часть инициализатора и соответствующие элементы будут инициализированы равными 0), простого пути не существует.
Не забывайте об очевидном решении, хотя:
Элементы с пропущенными значениями будут инициализированы в 0:
Так что это инициализирует все элементы в 0:
В C ++ пустой список инициализации также инициализирует каждый элемент в 0. Это не разрешено с C:
Помните, что объекты со статической длительностью хранения будут инициализированы в 0, если не указан инициализатор:
И то, что «0» не обязательно означает «все биты-ноль», поэтому использование вышеупомянутого лучше и более переносимо, чем memset (). (Значения с плавающей точкой будут инициализированы в +0, указатели на нулевое значение и т. Д.)
источник
Если ваш компилятор GCC, вы можете использовать следующий синтаксис:
Ознакомьтесь с подробным описанием: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html
источник
int
с в статические данные, что составляет 256 К - именно то увеличение размера, которое вы наблюдали.int
с, например,int foo1 = 1, foo2 = 1, ..., foo65536 =1;
вы получите такое же увеличение размера.bool array[][COLS] = { [0...ROWS-1][0...COLS-1] = true}
хотя я не уверен, что это более читабельно, чем полная форма.Для статической инициализации большого массива с одним и тем же значением без множественного копирования-вставки вы можете использовать макросы:
Если вам нужно изменить значение, вы должны сделать замену только в одном месте.
Редактировать: возможные полезные расширения
(любезно предоставлено Джонатаном Леффлером )
Вы можете легко обобщить это с помощью:
Вариант может быть создан с использованием:
это работает со структурами или составными массивами.
имена макросов являются предметом переговоров.
источник
VAL_1X
это не одно целое число, а список. Подобно состояниям Amigable, это также путь для встроенных систем, в которых вы хотите определить значения инициализации EEPROM или флэш-памяти. В обоих случаях вы не можете использоватьmemset()
.Если вы хотите, чтобы каждый член массива был явно инициализирован, просто пропустите измерение из объявления:
Компилятор выведет измерение из списка инициализатора. К сожалению, для многомерных массивов только самое внешнее измерение может быть опущено:
хорошо, но
не является.
источник
int myPoints[10][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
Я видел некоторый код, который использовал этот синтаксис:
Где это становится особенно полезным, если вы создаете массив, который использует перечисления в качестве индекса:
Это поддерживает порядок, даже если вы пишете некоторые из перечисляемых значений не по порядку.
Подробнее об этой технике можно узнать здесь и здесь .
источник
char const *array[] = { ... };
или дажеchar const * const array[] = { ... };
не так ли?Я думаю это лучше чем
Incase размер массива изменений.
источник
memset(myArray, VALUE, ARRAY_SIZE);
Вы можете выполнить всю статическую инициализацию, как описано выше, но это может быть настоящим обломом, когда размер вашего массива изменяется (когда ваш массив залипает, если вы не добавляете соответствующие дополнительные инициализаторы, вы получаете мусор).
memset дает вам попадание во время выполнения для выполнения работы, но ни одно правильное совпадение с размером кода не застраховано от изменений размера массива. Я бы использовал это решение почти во всех случаях, когда массив был больше, скажем, нескольких десятков элементов.
Если бы было действительно важно, чтобы массив был статически объявлен, я бы написал программу, которая напишет программу для меня и сделает ее частью процесса сборки.
источник
memset
для инициализации массива?Вот еще один способ:
Видеть:
C-расширения
Назначенные единицы
Затем задайте вопрос: когда можно использовать расширения C?
Пример кода выше находится во встроенной системе и никогда не увидит свет от другого компилятора.
источник
Для инициализации «нормальных» типов данных (таких как массивы int) вы можете использовать скобочную запись, но она обнулит значения после последней, если в массиве еще есть место:
источник
Если массив имеет тип int или что-либо с размером int или размер вашего mem-шаблона соответствует точному времени в int (т.е. все нули или 0xA5A5A5A5), лучшим способом является использование memset () .
В противном случае вызовите memcpy () в цикле, перемещающем индекс.
источник
Слегка насмешливый ответ; написать заявление
на вашем любимом языке с поддержкой массивов (мой - Fortran, но есть много других), и свяжите его с вашим C-кодом. Вы, вероятно, хотели бы обернуть это, чтобы быть внешней функцией.
источник
Существует быстрый способ инициализации массива любого типа с заданным значением. Это работает очень хорошо с большими массивами. Алгоритм заключается в следующем:
Для массива
1 000 000
элементовint
это в 4 раза быстрее обычной инициализации цикла (i5, 2 ядра, 2,3 ГГц, 4 ГБ памяти, 64 бита):loop runtime 0.004248 [seconds]
memfill() runtime 0.001085 [seconds]
источник
memfill()
код - около 1200 мкс. Однако на последующих итерациях цикл занимает около 900-1000 мкс, аmemfill()
код - 1000-1300 мкс. На первую итерацию, вероятно, влияет время заполнения кеша. Обратный тесты иmemfill()
медленный первый раз.Никто не упомянул порядок индексов для доступа к элементам инициализированного массива. Мой пример кода даст наглядный пример.
Выход:
источник
<iostream>
не действует ,C
какstd::cout
,std::cin
и т.д. является частьюstd::namespace
иC
не поддерживаетnamespaces
. Попробуйте использовать<stdio.h>
дляprintf(...)
вместо.Коротко отвечая на этот вопрос, можно сказать, что если вы включите оптимизацию во время компиляции, вы не добьетесь большего успеха, чем эта:
Дополнительный бонус: код на самом деле разборчивый :)
источник
пример: массив int [10]; memset (массив, -1, 10 * sizeof (int));
источник
Это даст o / p 5 5 5 5 5 5 ...... до размера всего массива
источник
Я знаю, что пользователь
Tarski
ответил на этот вопрос аналогичным образом, но я добавил еще несколько деталей. Простите за мой C, потому что я немного устала от этого, так как больше склоняюсь к тому, чтобы использовать C ++, но здесь все кончено.Если вы знаете размер массива раньше времени ...
Есть несколько предостережений выше; один из них заключается в том, что
UINT myArray[size];
он не инициализируется непосредственно при объявлении, однако следующий блок кода или вызов функции инициализирует каждый элемент массива тем же значением, которое вы хотите. Другое предостережение: вам нужно будет написатьinitializing function
для каждого, которыйtype
вы будете поддерживать, и вам также придется изменитьprintArray()
функцию для поддержки этих типов.Вы можете попробовать этот код с онлайн-компилятором, найденным здесь .
источник
Для отложенной инициализации (т.е. инициализации конструктора члена класса) рассмотрите:
источник
Я знаю, что в первоначальном вопросе явно упоминается C, а не C ++, но если вы (как и я) пришли сюда в поисках решения для массивов C ++, вот интересный трюк:
Если ваш компилятор поддерживает выражения сгиба , вы можете использовать магию шаблона и
std::index_sequence
сгенерировать список инициализаторов со значением, которое вы хотите. И вы можете дажеconstexpr
это и почувствовать себя боссомВы можете взглянуть на код на работе (в Wandbox)
источник
Я не вижу никаких требований в этом вопросе, поэтому решение должно быть общим: инициализация неопределенного, возможно, многомерного массива, построенного из неопределенных, возможно, элементов структуры с начальным значением члена:
Результат:
РЕДАКТИРОВАТЬ:
start+element_size
изменено на(char*)start+element_size
источник
sizeof(void)
является ли это действительным.memcpy()
перекрываются с местом назначения. При наивной реализацииmemcpy()
он может работать, но не обязательно, чтобы система работала.В свое время (и я не говорю, что это хорошая идея), мы установили первый элемент, а затем:
memcpy (&element [1], &element [0], sizeof (element)-sizeof (element [0]);
Даже не уверен, что он будет работать больше (это будет зависеть от реализации memcpy), но он работает путем многократного копирования исходного элемента в следующий - даже работает для массивов структур.
источник
memcpy
но указывали порядок копирования снизу вверх или сверху вниз в случае наложения, но это не так.memmove()
не делает это работает.Если вы имеете в виду параллельно, я думаю, что оператор запятой при использовании в сочетании с выражением может сделать это:
или если вы имеете в виду в одной конструкции, вы можете сделать это в цикле for:
// Обратите внимание, что оператор запятой в списке аргументов не является параллельным оператором, описанным выше;
Вы можете инициализировать замедление массива:
Вы можете вызвать malloc / calloc / sbrk / alloca / etc для выделения фиксированной области памяти для объекта:
и получить доступ к членам по:
И т.п.
источник