Инициализация нормального массива с одним значением по умолчанию

C ++ Примечания: Инициализация массива имеет хороший список для инициализации массивов. у меня есть

int array[100] = {-1}; 

ожидая, что он будет заполнен с -1, но его нет, только первое значение, а остальные 0 смешаны со случайными значениями.

Код

 int array[100] = {0}; 

отлично работает и устанавливает каждый элемент в 0.

Что мне здесь не хватает. Нельзя ли его инициализировать, если значение не равно нулю?

2: Является ли инициализация по умолчанию (как указано выше) быстрее, чем обычный цикл через весь массив, и присваивает значение или делает то же самое?

Используя синтаксис, который вы использовали,

 int array[100] = {-1}; 

говорит: «установите первый элемент -1 а остальное – 0 », так как все пропущенные элементы установлены в 0 .

В C ++, чтобы установить их все в -1 , вы можете использовать что-то вроде std::fill_n (from ):

 std::fill_n(array, 100, -1); 

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

Существует расширение для gcc-компилятора, который позволяет использовать синтаксис:

 int array[100] = { [0 ... 99] = -1 }; 

Это установило бы все элементы в -1.

Это называется «Назначенные инициализаторы», см. Здесь для получения дополнительной информации.

Обратите внимание, что это не реализовано для компилятора gcc c ++.

Страница, с которой вы связались, уже ответила на первую часть:

Если указан явный размер массива, но указывается более короткий список инициаций, неуказанные элементы устанавливаются равными нулю.

Нет встроенного способа инициализации всего массива некоторым ненулевым значением.

Что касается того, что происходит быстрее, применяется обычное правило: «Метод, который дает компилятору большую свободу, вероятно, быстрее».

 int array[100] = {0}; 

просто сообщает компилятору «установить эти 100 ints на ноль», которые компилятор может оптимизировать свободно.

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

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

Наконец, если вы хотите установить массив на ненулевое значение, вы должны (по крайней мере, на C ++) использовать std::fill :

 std::fill(array, array+100, 42); // sets every value in the array to 42 

Опять же, вы можете сделать то же самое с массивом, но это более кратким и дает компилятору больше свободы. Вы просто говорите, что хотите, чтобы весь массив заполнялся значением 42. Вы ничего не говорите, в каком порядке это должно быть сделано, или что-то еще.

C ++ 11 имеет другую (несовершенную) опцию:

 std::array a; a.fill(-1); 

С {} вы назначаете элементы по мере их объявления; остальное инициализируется 0.

Если для инициализации нет = {} , содержимое не определено.

Страница, с которой вы связываете состояния

Если указан явный размер массива, но указывается более короткий список инициаций, неуказанные элементы устанавливаются равными нулю.

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

Другим способом инициализации массива для общего значения было бы фактически сгенерировать список элементов из ряда определений:

 #define DUP1( X ) ( X ) #define DUP2( X ) DUP1( X ), ( X ) #define DUP3( X ) DUP2( X ), ( X ) #define DUP4( X ) DUP3( X ), ( X ) #define DUP5( X ) DUP4( X ), ( X ) . . #define DUP100( X ) DUP99( X ), ( X ) #define DUPx( X, N ) DUP##N( X ) #define DUP( X, N ) DUPx( X, N ) 

Инициализация массива на общее значение может быть легко выполнена:

 #define LIST_MAX 6 static unsigned char List[ LIST_MAX ]= { DUP( 123, LIST_MAX ) }; 

Примечание: DUPx введен для включения макроподстановки в параметрах в DUP

Используя std::array , мы можем сделать это довольно просто в C ++ 14. Это можно сделать только на C ++ 11, но немного сложнее.

Наш интерфейс – это размер времени компиляции и значение по умолчанию.

 template constexpr auto make_array_n(std::integral_constant, T &&) { return std::array, 0>{}; } template constexpr auto make_array_n(std::integral_constant, T && value) { return detail::make_array_n_impl(std::forward(value), std::make_index_sequence{}); } template constexpr auto make_array_n(T && value) { return make_array_n(std::integral_constant{}, std::forward(value)); } 

Третья функция в основном предназначена для удобства, поэтому пользователю не нужно создавать сами std::integral_constant , поскольку это довольно многословная конструкция. Реальная работа выполняется с помощью одной из первых двух функций.

Первая перегрузка довольно проста: он строит std::array размера 0. Нет необходимости в копировании, мы просто его создадим.

Вторая перегрузка немного сложнее. Он пересылает значение, полученное в качестве источника, а также создает экземпляр make_index_sequence и просто вызывает некоторую другую функцию реализации. Как выглядит эта функция?

 namespace detail { template constexpr auto make_array_n_impl(T && value, std::index_sequence) { // Use the comma operator to expand the variadic pack // Move the last element in if possible. Order of evaluation is well-defined // for aggregate initialization, so there is no risk of copy-after-move return std::array, size>{ (static_cast(indexes), value)..., std::forward(value) }; } } // namespace detail 

Это создает аргументы первого размера – 1, копируя переданное нами значение. Здесь мы используем наши индексы параметров вариационного параметра так же, как что-то для расширения. В этом пакете есть размер – 1 запись (как мы указали при построении make_index_sequence ), и они имеют значения 0, 1, 2, 3, …, размер – 2. Однако нам не нужны значения (поэтому мы отбрасываем его в пустоту, чтобы отключить любые предупреждения компилятора). Расширение пакета параметров расширяет наш код примерно так (при условии size == 4):

 return std::array, 4>{ (static_cast(0), value), (static_cast(1), value), (static_cast(2), value), std::forward(value) }; 

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

Последним аргументом, который мы называем std::forward on, является небольшая оптимизация. Если кто-то переходит во временную std :: string и говорит «сделать массив из 5 из них», мы хотели бы иметь 4 копии и 1 шаг вместо 5 копий. std::forward гарантирует, что мы это сделаем.

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

 #include  #include  #include  namespace detail { template constexpr auto make_array_n_impl(T && value, std::index_sequence) { // Use the comma operator to expand the variadic pack // Move the last element in if possible. Order of evaluation is well-defined // for aggregate initialization, so there is no risk of copy-after-move return std::array, size>{ (static_cast(indexes), value)..., std::forward(value) }; } } // namespace detail template constexpr auto make_array_n(std::integral_constant, T &&) { return std::array, 0>{}; } template constexpr auto make_array_n(std::integral_constant, T && value) { return detail::make_array_n_impl(std::forward(value), std::make_index_sequence{}); } template constexpr auto make_array_n(T && value) { return make_array_n(std::integral_constant{}, std::forward(value)); } struct non_copyable { constexpr non_copyable() = default; constexpr non_copyable(non_copyable const &) = delete; constexpr non_copyable(non_copyable &&) = default; }; int main() { constexpr auto array_n = make_array_n<6>(5); static_assert(std::is_same::value_type, int>::value, "Incorrect type from make_array_n."); static_assert(array_n.size() == 6, "Incorrect size from make_array_n."); static_assert(array_n[3] == 5, "Incorrect values from make_array_n."); constexpr auto array_non_copyable = make_array_n<1>(non_copyable{}); static_assert(array_non_copyable.size() == 1, "Incorrect array size of 1 for move-only types."); constexpr auto array_empty = make_array_n<0>(2); static_assert(array_empty.empty(), "Incorrect array size for empty array."); constexpr auto array_non_copyable_empty = make_array_n<0>(non_copyable{}); static_assert(array_non_copyable_empty.empty(), "Incorrect array size for empty array of move-only."); } 

1) Когда вы используете инициализатор, для структуры или такого массива, неустановленные значения по умолчанию построены по умолчанию. В случае примитивного типа типа ints это означает, что они будут обнулены. Обратите внимание, что это применяется рекурсивно: вы можете иметь массив структур, содержащих массивы, и если вы укажете только первое поле первой структуры, тогда все остальные будут инициализированы нулями и конструкторами по умолчанию.

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

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

Здесь есть пример.

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

На языке программирования C ++ V4, Stroustrup рекомендует использовать векторы или valarrays над встроенными массивами. С valarrary’s, когда вы их создаете, вы можете ввести их в определенное значение, например:

 valarray seven7s=(7777777,7); 

Чтобы инициализировать массив длиной 7 членов с помощью «7777777».

Это C ++ способ реализации ответа с использованием структуры данных C ++ вместо массива «простой старый C».

Я переключился на использование valarray как попытку в моем коде, чтобы попытаться использовать C ++ ‘isms v. C’isms ….

Должна быть стандартной функцией, но по какой-то причине она не включена в стандартный C или C ++ …

 #include  __asm__ ( " .global _arr; " " .section .data; " "_arr: .fill 100, 1, 2; " ); extern char arr[]; int main() { int i; for(i = 0; i < 100; ++i) { printf("arr[%u] = %u.\n", i, arr[i]); } } 

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

 program main implicit none byte a(100) data a /100*2/ integer i do i = 0, 100 print *, a(i) end do end 

но у него нет неподписанных чисел ...

Почему C / C ++ не может его реализовать. Неужели это так сложно? Так глупо писать это вручную, чтобы добиться того же результата ...

 #include  #include  /* did I count it correctly? I'm not quite sure. */ uint8_t arr = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, }; int main() { int i; for(i = 0; i < 100; ++i) { printf("arr[%u] = %u.\n", i, arr[i]); } } 

Что, если это массив из 1000,00 байт? Мне нужно написать сценарий, чтобы написать его для меня, или прибегнуть к хакам со сборкой / и т. Д. Это нонсенс.

Он совершенно портативен, нет причин, чтобы он не был на языке.

Просто взломайте его так:

 #include  #include  /* a byte array of 100 twos declared at compile time. */ uint8_t twos[] = {100:2}; int main() { uint_fast32_t i; for (i = 0; i < 100; ++i) { printf("twos[%u] = %u.\n", i, twos[i]); } return 0; } 

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

 #!/usr/bin/perl use warnings; use strict; open my $inf, "out.c"; my @lines = <$inf>; foreach my $line (@lines) { if ($line =~ m/({(\d+):(\d+)})/) { printf ("$1, $2, $3"); my $lnew = "{" . "$3, "x($2 - 1) . $3 . "}"; $line =~ s/{(\d+:\d+)}/$lnew/; printf $ouf $line; } else { printf $ouf $line; } } close($ouf); close($inf); 
  • Переадресация по умолчанию для Error 404
  • Force R не использовать экспоненциальную нотацию (например, e + 10)?
  • Значение по умолчанию для типа в Runtime
  • Почему в параметрах C ++ последнее значение должно быть добавлено последними?
  • Как заполнить / создать экземпляр массива C # с одним значением?
  • Интерфейс с методами по умолчанию vs Абстрактный class в Java 8
  • Можете ли вы вызвать метод по умолчанию родительского интерфейса из интерфейса, который подclassифицирует этот интерфейс?
  • Существует ли разумный подход к параметрам типа «по умолчанию» в C # Generics?
  • Изменить статус по умолчанию Magento для дублированных продуктов
  • Как открыть браузер по умолчанию в C #
  • Объявление примитивов / объектов, значения инициализации по умолчанию
  • Давайте будем гением компьютера.